Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 *
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;
47  q->sync_event_put = 0;
48  q->sync_time = 0;
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
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
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 */
88 }
89 
90 /*
91  * wait until the write buffer has enough room
92  */
93 int
95 {
96  struct seq_oss_devinfo *dp = q->dp;
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;
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;
119  }
120 
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
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
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
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