0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "seq_oss_timer.h"
0011 #include "seq_oss_event.h"
0012 #include <sound/seq_oss_legacy.h>
0013 #include <linux/slab.h>
0014
0015
0016
0017 #define MIN_OSS_TEMPO 8
0018 #define MAX_OSS_TEMPO 360
0019 #define MIN_OSS_TIMEBASE 1
0020 #define MAX_OSS_TIMEBASE 1000
0021
0022
0023
0024 static void calc_alsa_tempo(struct seq_oss_timer *timer);
0025 static int send_timer_event(struct seq_oss_devinfo *dp, int type, int value);
0026
0027
0028
0029
0030
0031
0032 struct seq_oss_timer *
0033 snd_seq_oss_timer_new(struct seq_oss_devinfo *dp)
0034 {
0035 struct seq_oss_timer *rec;
0036
0037 rec = kzalloc(sizeof(*rec), GFP_KERNEL);
0038 if (rec == NULL)
0039 return NULL;
0040
0041 rec->dp = dp;
0042 rec->cur_tick = 0;
0043 rec->realtime = 0;
0044 rec->running = 0;
0045 rec->oss_tempo = 60;
0046 rec->oss_timebase = 100;
0047 calc_alsa_tempo(rec);
0048
0049 return rec;
0050 }
0051
0052
0053
0054
0055
0056
0057 void
0058 snd_seq_oss_timer_delete(struct seq_oss_timer *rec)
0059 {
0060 if (rec) {
0061 snd_seq_oss_timer_stop(rec);
0062 kfree(rec);
0063 }
0064 }
0065
0066
0067
0068
0069
0070
0071
0072 int
0073 snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev)
0074 {
0075 abstime_t parm = ev->t.time;
0076
0077 if (ev->t.code == EV_TIMING) {
0078 switch (ev->t.cmd) {
0079 case TMR_WAIT_REL:
0080 parm += rec->cur_tick;
0081 rec->realtime = 0;
0082 fallthrough;
0083 case TMR_WAIT_ABS:
0084 if (parm == 0) {
0085 rec->realtime = 1;
0086 } else if (parm >= rec->cur_tick) {
0087 rec->realtime = 0;
0088 rec->cur_tick = parm;
0089 }
0090 return 1;
0091
0092 case TMR_START:
0093 snd_seq_oss_timer_start(rec);
0094 return 1;
0095
0096 }
0097 } else if (ev->s.code == SEQ_WAIT) {
0098
0099 parm = (ev->echo >> 8) & 0xffffff;
0100 if (parm > rec->cur_tick) {
0101
0102 rec->cur_tick = parm;
0103 rec->realtime = 0;
0104 }
0105 return 1;
0106 }
0107
0108 return 0;
0109 }
0110
0111
0112
0113
0114
0115 static void
0116 calc_alsa_tempo(struct seq_oss_timer *timer)
0117 {
0118 timer->tempo = (60 * 1000000) / timer->oss_tempo;
0119 timer->ppq = timer->oss_timebase;
0120 }
0121
0122
0123
0124
0125
0126 static int
0127 send_timer_event(struct seq_oss_devinfo *dp, int type, int value)
0128 {
0129 struct snd_seq_event ev;
0130
0131 memset(&ev, 0, sizeof(ev));
0132 ev.type = type;
0133 ev.source.client = dp->cseq;
0134 ev.source.port = 0;
0135 ev.dest.client = SNDRV_SEQ_CLIENT_SYSTEM;
0136 ev.dest.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
0137 ev.queue = dp->queue;
0138 ev.data.queue.queue = dp->queue;
0139 ev.data.queue.param.value = value;
0140 return snd_seq_kernel_client_dispatch(dp->cseq, &ev, 1, 0);
0141 }
0142
0143
0144
0145
0146 int
0147 snd_seq_oss_timer_start(struct seq_oss_timer *timer)
0148 {
0149 struct seq_oss_devinfo *dp = timer->dp;
0150 struct snd_seq_queue_tempo tmprec;
0151
0152 if (timer->running)
0153 snd_seq_oss_timer_stop(timer);
0154
0155 memset(&tmprec, 0, sizeof(tmprec));
0156 tmprec.queue = dp->queue;
0157 tmprec.ppq = timer->ppq;
0158 tmprec.tempo = timer->tempo;
0159 snd_seq_set_queue_tempo(dp->cseq, &tmprec);
0160
0161 send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
0162 timer->running = 1;
0163 timer->cur_tick = 0;
0164 return 0;
0165 }
0166
0167
0168
0169
0170
0171 int
0172 snd_seq_oss_timer_stop(struct seq_oss_timer *timer)
0173 {
0174 if (! timer->running)
0175 return 0;
0176 send_timer_event(timer->dp, SNDRV_SEQ_EVENT_STOP, 0);
0177 timer->running = 0;
0178 return 0;
0179 }
0180
0181
0182
0183
0184
0185 int
0186 snd_seq_oss_timer_continue(struct seq_oss_timer *timer)
0187 {
0188 if (timer->running)
0189 return 0;
0190 send_timer_event(timer->dp, SNDRV_SEQ_EVENT_CONTINUE, 0);
0191 timer->running = 1;
0192 return 0;
0193 }
0194
0195
0196
0197
0198
0199 int
0200 snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value)
0201 {
0202 if (value < MIN_OSS_TEMPO)
0203 value = MIN_OSS_TEMPO;
0204 else if (value > MAX_OSS_TEMPO)
0205 value = MAX_OSS_TEMPO;
0206 timer->oss_tempo = value;
0207 calc_alsa_tempo(timer);
0208 if (timer->running)
0209 send_timer_event(timer->dp, SNDRV_SEQ_EVENT_TEMPO, timer->tempo);
0210 return 0;
0211 }
0212
0213
0214
0215
0216
0217 int
0218 snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg)
0219 {
0220 int value;
0221
0222 if (cmd == SNDCTL_SEQ_CTRLRATE) {
0223
0224 if (get_user(value, arg))
0225 return -EFAULT;
0226 if (value)
0227 return -EINVAL;
0228 value = ((timer->oss_tempo * timer->oss_timebase) + 30) / 60;
0229 return put_user(value, arg) ? -EFAULT : 0;
0230 }
0231
0232 if (timer->dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
0233 return 0;
0234
0235 switch (cmd) {
0236 case SNDCTL_TMR_START:
0237 return snd_seq_oss_timer_start(timer);
0238 case SNDCTL_TMR_STOP:
0239 return snd_seq_oss_timer_stop(timer);
0240 case SNDCTL_TMR_CONTINUE:
0241 return snd_seq_oss_timer_continue(timer);
0242 case SNDCTL_TMR_TEMPO:
0243 if (get_user(value, arg))
0244 return -EFAULT;
0245 return snd_seq_oss_timer_tempo(timer, value);
0246 case SNDCTL_TMR_TIMEBASE:
0247 if (get_user(value, arg))
0248 return -EFAULT;
0249 if (value < MIN_OSS_TIMEBASE)
0250 value = MIN_OSS_TIMEBASE;
0251 else if (value > MAX_OSS_TIMEBASE)
0252 value = MAX_OSS_TIMEBASE;
0253 timer->oss_timebase = value;
0254 calc_alsa_tempo(timer);
0255 return 0;
0256
0257 case SNDCTL_TMR_METRONOME:
0258 case SNDCTL_TMR_SELECT:
0259 case SNDCTL_TMR_SOURCE:
0260
0261 return 0;
0262 }
0263 return 0;
0264 }