Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
sound
core
seq
oss
seq_oss_rw.c
Go to the documentation of this file.
1
/*
2
* OSS compatible sequencer driver
3
*
4
* read/write/select interface to device file
5
*
6
* Copyright (C) 1998,99 Takashi Iwai <
[email protected]
>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
23
#include "
seq_oss_device.h
"
24
#include "
seq_oss_readq.h
"
25
#include "
seq_oss_writeq.h
"
26
#include "
seq_oss_synth.h
"
27
#include <
sound/seq_oss_legacy.h
>
28
#include "
seq_oss_event.h
"
29
#include "
seq_oss_timer.h
"
30
#include "../seq_clientmgr.h"
31
32
33
/*
34
* protoypes
35
*/
36
static
int
insert_queue(
struct
seq_oss_devinfo
*
dp
,
union
evrec
*rec,
struct
file
*
opt
);
37
38
39
/*
40
* read interface
41
*/
42
43
int
44
snd_seq_oss_read
(
struct
seq_oss_devinfo
*
dp
,
char
__user *
buf
,
int
count
)
45
{
46
struct
seq_oss_readq
*
readq
= dp->
readq
;
47
int
result
= 0,
err
= 0;
48
int
ev_len;
49
union
evrec
rec;
50
unsigned
long
flags
;
51
52
if
(readq ==
NULL
|| !
is_read_mode
(dp->
file_mode
))
53
return
-
ENXIO
;
54
55
while
(count >=
SHORT_EVENT_SIZE
) {
56
snd_seq_oss_readq_lock
(readq, flags);
57
err
=
snd_seq_oss_readq_pick
(readq, &rec);
58
if
(
err
== -
EAGAIN
&&
59
!
is_nonblock_mode
(dp->
file_mode
) && result == 0) {
60
snd_seq_oss_readq_unlock
(readq, flags);
61
snd_seq_oss_readq_wait
(readq);
62
snd_seq_oss_readq_lock
(readq, flags);
63
if
(signal_pending(
current
))
64
err
= -
ERESTARTSYS
;
65
else
66
err
=
snd_seq_oss_readq_pick
(readq, &rec);
67
}
68
if
(
err
< 0) {
69
snd_seq_oss_readq_unlock
(readq, flags);
70
break
;
71
}
72
ev_len =
ev_length
(&rec);
73
if
(ev_len < count) {
74
snd_seq_oss_readq_unlock
(readq, flags);
75
break
;
76
}
77
snd_seq_oss_readq_free
(readq);
78
snd_seq_oss_readq_unlock
(readq, flags);
79
if
(
copy_to_user
(buf, &rec, ev_len)) {
80
err
= -
EFAULT
;
81
break
;
82
}
83
result += ev_len;
84
buf += ev_len;
85
count -= ev_len;
86
}
87
return
result > 0 ? result :
err
;
88
}
89
90
91
/*
92
* write interface
93
*/
94
95
int
96
snd_seq_oss_write
(
struct
seq_oss_devinfo
*
dp
,
const
char
__user *
buf
,
int
count
,
struct
file
*
opt
)
97
{
98
int
result
= 0,
err
= 0;
99
int
ev_size,
fmt
;
100
union
evrec
rec;
101
102
if
(!
is_write_mode
(dp->
file_mode
) || dp->
writeq
==
NULL
)
103
return
-
ENXIO
;
104
105
while
(count >=
SHORT_EVENT_SIZE
) {
106
if
(
copy_from_user
(&rec, buf,
SHORT_EVENT_SIZE
)) {
107
err
= -
EFAULT
;
108
break
;
109
}
110
if
(rec.
s
.code ==
SEQ_FULLSIZE
) {
111
/* load patch */
112
if
(result > 0) {
113
err
= -
EINVAL
;
114
break
;
115
}
116
fmt = (*(
unsigned
short
*)rec.
c
) & 0xffff;
117
/* FIXME the return value isn't correct */
118
return
snd_seq_oss_synth_load_patch
(dp, rec.
s
.dev,
119
fmt, buf, 0, count);
120
}
121
if
(
ev_is_long
(&rec)) {
122
/* extended code */
123
if
(rec.
s
.code ==
SEQ_EXTENDED
&&
124
dp->
seq_mode
==
SNDRV_SEQ_OSS_MODE_MUSIC
) {
125
err
= -
EINVAL
;
126
break
;
127
}
128
ev_size =
LONG_EVENT_SIZE
;
129
if
(count < ev_size)
130
break
;
131
/* copy the reset 4 bytes */
132
if
(
copy_from_user
(rec.
c
+
SHORT_EVENT_SIZE
,
133
buf +
SHORT_EVENT_SIZE
,
134
LONG_EVENT_SIZE
-
SHORT_EVENT_SIZE
)) {
135
err
= -
EFAULT
;
136
break
;
137
}
138
}
else
{
139
/* old-type code */
140
if
(dp->
seq_mode
==
SNDRV_SEQ_OSS_MODE_MUSIC
) {
141
err
= -
EINVAL
;
142
break
;
143
}
144
ev_size =
SHORT_EVENT_SIZE
;
145
}
146
147
/* insert queue */
148
if
((
err
= insert_queue(dp, &rec, opt)) < 0)
149
break
;
150
151
result += ev_size;
152
buf += ev_size;
153
count -= ev_size;
154
}
155
return
result > 0 ? result :
err
;
156
}
157
158
159
/*
160
* insert event record to write queue
161
* return: 0 = OK, non-zero = NG
162
*/
163
static
int
164
insert_queue(
struct
seq_oss_devinfo
*
dp
,
union
evrec
*rec,
struct
file
*
opt
)
165
{
166
int
rc
= 0;
167
struct
snd_seq_event
event
;
168
169
/* if this is a timing event, process the current time */
170
if
(
snd_seq_oss_process_timer_event
(dp->
timer
, rec))
171
return
0;
/* no need to insert queue */
172
173
/* parse this event */
174
memset
(&
event
, 0,
sizeof
(
event
));
175
/* set dummy -- to be sure */
176
event
.type =
SNDRV_SEQ_EVENT_NOTEOFF
;
177
snd_seq_oss_fill_addr(dp, &
event
, dp->
addr
.port, dp->
addr
.client);
178
179
if
(
snd_seq_oss_process_event
(dp, rec, &
event
))
180
return
0;
/* invalid event - no need to insert queue */
181
182
event
.time.tick = snd_seq_oss_timer_cur_tick(dp->
timer
);
183
if
(dp->
timer
->realtime || !dp->
timer
->running) {
184
snd_seq_oss_dispatch(dp, &
event
, 0, 0);
185
}
else
{
186
if
(
is_nonblock_mode
(dp->
file_mode
))
187
rc =
snd_seq_kernel_client_enqueue
(dp->
cseq
, &
event
, 0, 0);
188
else
189
rc =
snd_seq_kernel_client_enqueue_blocking
(dp->
cseq
, &
event
, opt, 0, 0);
190
}
191
return
rc
;
192
}
193
194
195
/*
196
* select / poll
197
*/
198
199
unsigned
int
200
snd_seq_oss_poll
(
struct
seq_oss_devinfo
*dp,
struct
file
*
file
,
poll_table
*
wait
)
201
{
202
unsigned
int
mask
= 0;
203
204
/* input */
205
if
(dp->
readq
&&
is_read_mode
(dp->
file_mode
)) {
206
if
(
snd_seq_oss_readq_poll
(dp->
readq
, file, wait))
207
mask |=
POLLIN
|
POLLRDNORM
;
208
}
209
210
/* output */
211
if
(dp->
writeq
&&
is_write_mode
(dp->
file_mode
)) {
212
if
(
snd_seq_kernel_client_write_poll
(dp->
cseq
, file, wait))
213
mask |=
POLLOUT
|
POLLWRNORM
;
214
}
215
return
mask
;
216
}
Generated on Thu Jan 10 2013 15:03:59 for Linux Kernel by
1.8.2