0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "seq_oss_readq.h"
0011 #include "seq_oss_event.h"
0012 #include <sound/seq_oss_legacy.h>
0013 #include "../seq_lock.h"
0014 #include <linux/wait.h>
0015 #include <linux/slab.h>
0016
0017
0018
0019
0020
0021 #define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600)
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 struct seq_oss_readq *
0033 snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
0034 {
0035 struct seq_oss_readq *q;
0036
0037 q = kzalloc(sizeof(*q), GFP_KERNEL);
0038 if (!q)
0039 return NULL;
0040
0041 q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL);
0042 if (!q->q) {
0043 kfree(q);
0044 return NULL;
0045 }
0046
0047 q->maxlen = maxlen;
0048 q->qlen = 0;
0049 q->head = q->tail = 0;
0050 init_waitqueue_head(&q->midi_sleep);
0051 spin_lock_init(&q->lock);
0052 q->pre_event_timeout = SNDRV_SEQ_OSS_MAX_TIMEOUT;
0053 q->input_time = (unsigned long)-1;
0054
0055 return q;
0056 }
0057
0058
0059
0060
0061 void
0062 snd_seq_oss_readq_delete(struct seq_oss_readq *q)
0063 {
0064 if (q) {
0065 kfree(q->q);
0066 kfree(q);
0067 }
0068 }
0069
0070
0071
0072
0073 void
0074 snd_seq_oss_readq_clear(struct seq_oss_readq *q)
0075 {
0076 if (q->qlen) {
0077 q->qlen = 0;
0078 q->head = q->tail = 0;
0079 }
0080
0081 wake_up(&q->midi_sleep);
0082 q->input_time = (unsigned long)-1;
0083 }
0084
0085
0086
0087
0088 int
0089 snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len)
0090 {
0091 union evrec rec;
0092 int result;
0093
0094 memset(&rec, 0, sizeof(rec));
0095 rec.c[0] = SEQ_MIDIPUTC;
0096 rec.c[2] = dev;
0097
0098 while (len-- > 0) {
0099 rec.c[1] = *data++;
0100 result = snd_seq_oss_readq_put_event(q, &rec);
0101 if (result < 0)
0102 return result;
0103 }
0104 return 0;
0105 }
0106
0107
0108
0109
0110
0111 struct readq_sysex_ctx {
0112 struct seq_oss_readq *readq;
0113 int dev;
0114 };
0115
0116 static int readq_dump_sysex(void *ptr, void *buf, int count)
0117 {
0118 struct readq_sysex_ctx *ctx = ptr;
0119
0120 return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count);
0121 }
0122
0123 int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
0124 struct snd_seq_event *ev)
0125 {
0126 struct readq_sysex_ctx ctx = {
0127 .readq = q,
0128 .dev = dev
0129 };
0130
0131 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
0132 return 0;
0133 return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx);
0134 }
0135
0136
0137
0138
0139
0140 int
0141 snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
0142 {
0143 unsigned long flags;
0144
0145 spin_lock_irqsave(&q->lock, flags);
0146 if (q->qlen >= q->maxlen - 1) {
0147 spin_unlock_irqrestore(&q->lock, flags);
0148 return -ENOMEM;
0149 }
0150
0151 memcpy(&q->q[q->tail], ev, sizeof(*ev));
0152 q->tail = (q->tail + 1) % q->maxlen;
0153 q->qlen++;
0154
0155
0156 wake_up(&q->midi_sleep);
0157
0158 spin_unlock_irqrestore(&q->lock, flags);
0159
0160 return 0;
0161 }
0162
0163
0164
0165
0166
0167
0168 int
0169 snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec)
0170 {
0171 if (q->qlen == 0)
0172 return -EAGAIN;
0173 memcpy(rec, &q->q[q->head], sizeof(*rec));
0174 return 0;
0175 }
0176
0177
0178
0179
0180 void
0181 snd_seq_oss_readq_wait(struct seq_oss_readq *q)
0182 {
0183 wait_event_interruptible_timeout(q->midi_sleep,
0184 (q->qlen > 0 || q->head == q->tail),
0185 q->pre_event_timeout);
0186 }
0187
0188
0189
0190
0191
0192 void
0193 snd_seq_oss_readq_free(struct seq_oss_readq *q)
0194 {
0195 if (q->qlen > 0) {
0196 q->head = (q->head + 1) % q->maxlen;
0197 q->qlen--;
0198 }
0199 }
0200
0201
0202
0203
0204
0205 unsigned int
0206 snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait)
0207 {
0208 poll_wait(file, &q->midi_sleep, wait);
0209 return q->qlen;
0210 }
0211
0212
0213
0214
0215 int
0216 snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
0217 {
0218 if (curt != q->input_time) {
0219 union evrec rec;
0220 memset(&rec, 0, sizeof(rec));
0221 switch (seq_mode) {
0222 case SNDRV_SEQ_OSS_MODE_SYNTH:
0223 rec.echo = (curt << 8) | SEQ_WAIT;
0224 snd_seq_oss_readq_put_event(q, &rec);
0225 break;
0226 case SNDRV_SEQ_OSS_MODE_MUSIC:
0227 rec.t.code = EV_TIMING;
0228 rec.t.cmd = TMR_WAIT_ABS;
0229 rec.t.time = curt;
0230 snd_seq_oss_readq_put_event(q, &rec);
0231 break;
0232 }
0233 q->input_time = curt;
0234 }
0235 return 0;
0236 }
0237
0238
0239 #ifdef CONFIG_SND_PROC_FS
0240
0241
0242
0243 void
0244 snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf)
0245 {
0246 snd_iprintf(buf, " read queue [%s] length = %d : tick = %ld\n",
0247 (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"),
0248 q->qlen, q->input_time);
0249 }
0250 #endif