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_writeq.c
Go to the documentation of this file.
1
/*
2
* OSS compatible sequencer driver
3
*
4
* seq_oss_writeq.c - write queue and sync
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_writeq.h
"
24
#include "
seq_oss_event.h
"
25
#include "
seq_oss_timer.h
"
26
#include <
sound/seq_oss_legacy.h
>
27
#include "../seq_lock.h"
28
#include "../seq_clientmgr.h"
29
#include <linux/wait.h>
30
#include <linux/slab.h>
31
32
33
/*
34
* create a write queue record
35
*/
36
struct
seq_oss_writeq
*
37
snd_seq_oss_writeq_new
(
struct
seq_oss_devinfo
*
dp
,
int
maxlen
)
38
{
39
struct
seq_oss_writeq
*
q
;
40
struct
snd_seq_client_pool
pool;
41
42
if
((q = kzalloc(
sizeof
(*q),
GFP_KERNEL
)) ==
NULL
)
43
return
NULL
;
44
q->
dp
=
dp
;
45
q->
maxlen
= maxlen;
46
spin_lock_init
(&q->
sync_lock
);
47
q->
sync_event_put
= 0;
48
q->
sync_time
= 0;
49
init_waitqueue_head
(&q->
sync_sleep
);
50
51
memset
(&pool, 0,
sizeof
(pool));
52
pool.
client
= dp->
cseq
;
53
pool.
output_pool
= maxlen;
54
pool.
output_room
= maxlen / 2;
55
56
snd_seq_oss_control(dp,
SNDRV_SEQ_IOCTL_SET_CLIENT_POOL
, &pool);
57
58
return
q
;
59
}
60
61
/*
62
* delete the write queue
63
*/
64
void
65
snd_seq_oss_writeq_delete
(
struct
seq_oss_writeq
*
q
)
66
{
67
if
(q) {
68
snd_seq_oss_writeq_clear
(q);
/* to be sure */
69
kfree
(q);
70
}
71
}
72
73
74
/*
75
* reset the write queue
76
*/
77
void
78
snd_seq_oss_writeq_clear
(
struct
seq_oss_writeq
*
q
)
79
{
80
struct
snd_seq_remove_events
reset;
81
82
memset
(&reset, 0,
sizeof
(reset));
83
reset.
remove_mode
=
SNDRV_SEQ_REMOVE_OUTPUT
;
/* remove all */
84
snd_seq_oss_control(q->
dp
,
SNDRV_SEQ_IOCTL_REMOVE_EVENTS
, &reset);
85
86
/* wake up sleepers if any */
87
snd_seq_oss_writeq_wakeup
(q, 0);
88
}
89
90
/*
91
* wait until the write buffer has enough room
92
*/
93
int
94
snd_seq_oss_writeq_sync
(
struct
seq_oss_writeq
*
q
)
95
{
96
struct
seq_oss_devinfo
*
dp
= q->
dp
;
97
abstime_t
time
;
98
99
time = snd_seq_oss_timer_cur_tick(dp->
timer
);
100
if
(q->
sync_time
>= time)
101
return
0;
/* already finished */
102
103
if
(! q->
sync_event_put
) {
104
struct
snd_seq_event
ev;
105
union
evrec
*rec;
106
107
/* put echoback event */
108
memset
(&ev, 0,
sizeof
(ev));
109
ev.
flags
= 0;
110
ev.
type
=
SNDRV_SEQ_EVENT_ECHO
;
111
ev.
time
.
tick
=
time
;
112
/* echo back to itself */
113
snd_seq_oss_fill_addr(dp, &ev, dp->
addr
.client, dp->
addr
.port);
114
rec = (
union
evrec
*)&ev.
data
;
115
rec->
t
.code =
SEQ_SYNCTIMER
;
116
rec->
t
.time = time;
117
q->
sync_event_put
= 1;
118
snd_seq_kernel_client_enqueue_blocking
(dp->
cseq
, &ev,
NULL
, 0, 0);
119
}
120
121
wait_event_interruptible_timeout
(q->
sync_sleep
, ! q->
sync_event_put
,
HZ
);
122
if
(signal_pending(
current
))
123
/* interrupted - return 0 to finish sync */
124
q->
sync_event_put
= 0;
125
if
(! q->
sync_event_put
|| q->
sync_time
>= time)
126
return
0;
127
return
1;
128
}
129
130
/*
131
* wake up sync - echo event was catched
132
*/
133
void
134
snd_seq_oss_writeq_wakeup
(
struct
seq_oss_writeq
*
q
,
abstime_t
time
)
135
{
136
unsigned
long
flags
;
137
138
spin_lock_irqsave
(&q->
sync_lock
, flags);
139
q->
sync_time
=
time
;
140
q->
sync_event_put
= 0;
141
if
(waitqueue_active(&q->
sync_sleep
)) {
142
wake_up
(&q->
sync_sleep
);
143
}
144
spin_unlock_irqrestore(&q->
sync_lock
, flags);
145
}
146
147
148
/*
149
* return the unused pool size
150
*/
151
int
152
snd_seq_oss_writeq_get_free_size
(
struct
seq_oss_writeq
*
q
)
153
{
154
struct
snd_seq_client_pool
pool;
155
pool.
client
= q->
dp
->cseq;
156
snd_seq_oss_control(q->
dp
,
SNDRV_SEQ_IOCTL_GET_CLIENT_POOL
, &pool);
157
return
pool.
output_free
;
158
}
159
160
161
/*
162
* set output threshold size from ioctl
163
*/
164
void
165
snd_seq_oss_writeq_set_output
(
struct
seq_oss_writeq
*
q
,
int
val
)
166
{
167
struct
snd_seq_client_pool
pool;
168
pool.
client
= q->
dp
->cseq;
169
snd_seq_oss_control(q->
dp
,
SNDRV_SEQ_IOCTL_GET_CLIENT_POOL
, &pool);
170
pool.
output_room
=
val
;
171
snd_seq_oss_control(q->
dp
,
SNDRV_SEQ_IOCTL_SET_CLIENT_POOL
, &pool);
172
}
173
Generated on Thu Jan 10 2013 15:03:59 for Linux Kernel by
1.8.2