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_readq.c
Go to the documentation of this file.
1
/*
2
* OSS compatible sequencer driver
3
*
4
* seq_oss_readq.c - MIDI input queue
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_readq.h
"
24
#include "
seq_oss_event.h
"
25
#include <
sound/seq_oss_legacy.h
>
26
#include "../seq_lock.h"
27
#include <linux/wait.h>
28
#include <linux/slab.h>
29
30
/*
31
* constants
32
*/
33
//#define SNDRV_SEQ_OSS_MAX_TIMEOUT (unsigned long)(-1)
34
#define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600)
35
36
37
/*
38
* prototypes
39
*/
40
41
42
/*
43
* create a read queue
44
*/
45
struct
seq_oss_readq
*
46
snd_seq_oss_readq_new
(
struct
seq_oss_devinfo
*
dp
,
int
maxlen
)
47
{
48
struct
seq_oss_readq
*
q
;
49
50
if
((q = kzalloc(
sizeof
(*q),
GFP_KERNEL
)) ==
NULL
) {
51
snd_printk
(
KERN_ERR
"can't malloc read queue\n"
);
52
return
NULL
;
53
}
54
55
if
((q->
q
= kcalloc(maxlen,
sizeof
(
union
evrec
),
GFP_KERNEL
)) ==
NULL
) {
56
snd_printk
(
KERN_ERR
"can't malloc read queue buffer\n"
);
57
kfree
(q);
58
return
NULL
;
59
}
60
61
q->
maxlen
=
maxlen
;
62
q->
qlen
= 0;
63
q->
head
= q->
tail
= 0;
64
init_waitqueue_head
(&q->
midi_sleep
);
65
spin_lock_init
(&q->
lock
);
66
q->
pre_event_timeout
=
SNDRV_SEQ_OSS_MAX_TIMEOUT
;
67
q->
input_time
= (
unsigned
long
)-1;
68
69
return
q
;
70
}
71
72
/*
73
* delete the read queue
74
*/
75
void
76
snd_seq_oss_readq_delete
(
struct
seq_oss_readq
*
q
)
77
{
78
if
(q) {
79
kfree
(q->
q
);
80
kfree
(q);
81
}
82
}
83
84
/*
85
* reset the read queue
86
*/
87
void
88
snd_seq_oss_readq_clear
(
struct
seq_oss_readq
*
q
)
89
{
90
if
(q->
qlen
) {
91
q->
qlen
= 0;
92
q->
head
= q->
tail
= 0;
93
}
94
/* if someone sleeping, wake'em up */
95
if
(waitqueue_active(&q->
midi_sleep
))
96
wake_up
(&q->
midi_sleep
);
97
q->
input_time
= (
unsigned
long
)-1;
98
}
99
100
/*
101
* put a midi byte
102
*/
103
int
104
snd_seq_oss_readq_puts
(
struct
seq_oss_readq
*
q
,
int
dev
,
unsigned
char
*
data
,
int
len)
105
{
106
union
evrec
rec;
107
int
result
;
108
109
memset
(&rec, 0,
sizeof
(rec));
110
rec.
c
[0] =
SEQ_MIDIPUTC
;
111
rec.
c
[2] =
dev
;
112
113
while
(len-- > 0) {
114
rec.
c
[1] = *data++;
115
result =
snd_seq_oss_readq_put_event
(q, &rec);
116
if
(result < 0)
117
return
result
;
118
}
119
return
0;
120
}
121
122
/*
123
* copy an event to input queue:
124
* return zero if enqueued
125
*/
126
int
127
snd_seq_oss_readq_put_event
(
struct
seq_oss_readq
*
q
,
union
evrec
*ev)
128
{
129
unsigned
long
flags
;
130
131
spin_lock_irqsave
(&q->
lock
, flags);
132
if
(q->
qlen
>= q->
maxlen
- 1) {
133
spin_unlock_irqrestore(&q->
lock
, flags);
134
return
-
ENOMEM
;
135
}
136
137
memcpy
(&q->
q
[q->
tail
], ev,
sizeof
(*ev));
138
q->
tail
= (q->
tail
+ 1) % q->
maxlen
;
139
q->
qlen
++;
140
141
/* wake up sleeper */
142
if
(waitqueue_active(&q->
midi_sleep
))
143
wake_up
(&q->
midi_sleep
);
144
145
spin_unlock_irqrestore(&q->
lock
, flags);
146
147
return
0;
148
}
149
150
151
/*
152
* pop queue
153
* caller must hold lock
154
*/
155
int
156
snd_seq_oss_readq_pick
(
struct
seq_oss_readq
*
q
,
union
evrec
*rec)
157
{
158
if
(q->
qlen
== 0)
159
return
-
EAGAIN
;
160
memcpy
(rec, &q->
q
[q->
head
],
sizeof
(*rec));
161
return
0;
162
}
163
164
/*
165
* sleep until ready
166
*/
167
void
168
snd_seq_oss_readq_wait
(
struct
seq_oss_readq
*
q
)
169
{
170
wait_event_interruptible_timeout
(q->
midi_sleep
,
171
(q->
qlen
> 0 || q->
head
== q->
tail
),
172
q->
pre_event_timeout
);
173
}
174
175
/*
176
* drain one record
177
* caller must hold lock
178
*/
179
void
180
snd_seq_oss_readq_free
(
struct
seq_oss_readq
*
q
)
181
{
182
if
(q->
qlen
> 0) {
183
q->
head
= (q->
head
+ 1) % q->
maxlen
;
184
q->
qlen
--;
185
}
186
}
187
188
/*
189
* polling/select:
190
* return non-zero if readq is not empty.
191
*/
192
unsigned
int
193
snd_seq_oss_readq_poll
(
struct
seq_oss_readq
*
q
,
struct
file
*
file
,
poll_table
*
wait
)
194
{
195
poll_wait(file, &q->
midi_sleep
, wait);
196
return
q->
qlen
;
197
}
198
199
/*
200
* put a timestamp
201
*/
202
int
203
snd_seq_oss_readq_put_timestamp
(
struct
seq_oss_readq
*
q
,
unsigned
long
curt,
int
seq_mode)
204
{
205
if
(curt != q->
input_time
) {
206
union
evrec
rec;
207
memset
(&rec, 0,
sizeof
(rec));
208
switch
(seq_mode) {
209
case
SNDRV_SEQ_OSS_MODE_SYNTH
:
210
rec.
echo
= (curt << 8) |
SEQ_WAIT
;
211
snd_seq_oss_readq_put_event
(q, &rec);
212
break
;
213
case
SNDRV_SEQ_OSS_MODE_MUSIC
:
214
rec.
t
.code =
EV_TIMING
;
215
rec.
t
.cmd =
TMR_WAIT_ABS
;
216
rec.
t
.time = curt;
217
snd_seq_oss_readq_put_event
(q, &rec);
218
break
;
219
}
220
q->
input_time
= curt;
221
}
222
return
0;
223
}
224
225
226
#ifdef CONFIG_PROC_FS
227
/*
228
* proc interface
229
*/
230
void
231
snd_seq_oss_readq_info_read
(
struct
seq_oss_readq
*
q
,
struct
snd_info_buffer
*
buf
)
232
{
233
snd_iprintf(buf,
" read queue [%s] length = %d : tick = %ld\n"
,
234
(waitqueue_active(&q->
midi_sleep
) ?
"sleeping"
:
"running"
),
235
q->
qlen
, q->
input_time
);
236
}
237
#endif
/* CONFIG_PROC_FS */
Generated on Thu Jan 10 2013 15:03:58 for Linux Kernel by
1.8.2