~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/core/seq/oss/seq_oss_midi.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * OSS compatible sequencer driver
  4  *
  5  * MIDI device handlers
  6  *
  7  * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
  8  */
  9 
 10 #include <sound/asoundef.h>
 11 #include "seq_oss_midi.h"
 12 #include "seq_oss_readq.h"
 13 #include "seq_oss_timer.h"
 14 #include "seq_oss_event.h"
 15 #include <sound/seq_midi_event.h>
 16 #include "../seq_lock.h"
 17 #include <linux/init.h>
 18 #include <linux/slab.h>
 19 #include <linux/nospec.h>
 20 
 21 
 22 /*
 23  * constants
 24  */
 25 #define SNDRV_SEQ_OSS_MAX_MIDI_NAME     30
 26 
 27 /*
 28  * definition of midi device record
 29  */
 30 struct seq_oss_midi {
 31         int seq_device;         /* device number */
 32         int client;             /* sequencer client number */
 33         int port;               /* sequencer port number */
 34         unsigned int flags;     /* port capability */
 35         int opened;             /* flag for opening */
 36         unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
 37         struct snd_midi_event *coder;   /* MIDI event coder */
 38         struct seq_oss_devinfo *devinfo;        /* assigned OSSseq device */
 39         snd_use_lock_t use_lock;
 40         struct mutex open_mutex;
 41 };
 42 
 43 
 44 /*
 45  * midi device table
 46  */
 47 static int max_midi_devs;
 48 static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
 49 
 50 static DEFINE_SPINLOCK(register_lock);
 51 
 52 /*
 53  * prototypes
 54  */
 55 static struct seq_oss_midi *get_mdev(int dev);
 56 static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
 57 static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
 58 static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
 59 
 60 /*
 61  * look up the existing ports
 62  * this looks a very exhausting job.
 63  */
 64 int
 65 snd_seq_oss_midi_lookup_ports(int client)
 66 {
 67         struct snd_seq_client_info *clinfo __free(kfree) = NULL;
 68         struct snd_seq_port_info *pinfo __free(kfree) = NULL;
 69 
 70         clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
 71         pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
 72         if (!clinfo || !pinfo)
 73                 return -ENOMEM;
 74         clinfo->client = -1;
 75         while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
 76                 if (clinfo->client == client)
 77                         continue; /* ignore myself */
 78                 pinfo->addr.client = clinfo->client;
 79                 pinfo->addr.port = -1;
 80                 while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
 81                         snd_seq_oss_midi_check_new_port(pinfo);
 82         }
 83         return 0;
 84 }
 85 
 86 
 87 /*
 88  */
 89 static struct seq_oss_midi *
 90 get_mdev(int dev)
 91 {
 92         struct seq_oss_midi *mdev;
 93         unsigned long flags;
 94 
 95         spin_lock_irqsave(&register_lock, flags);
 96         mdev = midi_devs[dev];
 97         if (mdev)
 98                 snd_use_lock_use(&mdev->use_lock);
 99         spin_unlock_irqrestore(&register_lock, flags);
100         return mdev;
101 }
102 
103 /*
104  * look for the identical slot
105  */
106 static struct seq_oss_midi *
107 find_slot(int client, int port)
108 {
109         int i;
110         struct seq_oss_midi *mdev;
111         unsigned long flags;
112 
113         spin_lock_irqsave(&register_lock, flags);
114         for (i = 0; i < max_midi_devs; i++) {
115                 mdev = midi_devs[i];
116                 if (mdev && mdev->client == client && mdev->port == port) {
117                         /* found! */
118                         snd_use_lock_use(&mdev->use_lock);
119                         spin_unlock_irqrestore(&register_lock, flags);
120                         return mdev;
121                 }
122         }
123         spin_unlock_irqrestore(&register_lock, flags);
124         return NULL;
125 }
126 
127 
128 #define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
129 #define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
130 /*
131  * register a new port if it doesn't exist yet
132  */
133 int
134 snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
135 {
136         int i;
137         struct seq_oss_midi *mdev;
138         unsigned long flags;
139 
140         /* the port must include generic midi */
141         if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
142                 return 0;
143         /* either read or write subscribable */
144         if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
145             (pinfo->capability & PERM_READ) != PERM_READ)
146                 return 0;
147 
148         /*
149          * look for the identical slot
150          */
151         mdev = find_slot(pinfo->addr.client, pinfo->addr.port);
152         if (mdev) {
153                 /* already exists */
154                 snd_use_lock_free(&mdev->use_lock);
155                 return 0;
156         }
157 
158         /*
159          * allocate midi info record
160          */
161         mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
162         if (!mdev)
163                 return -ENOMEM;
164 
165         /* copy the port information */
166         mdev->client = pinfo->addr.client;
167         mdev->port = pinfo->addr.port;
168         mdev->flags = pinfo->capability;
169         mdev->opened = 0;
170         snd_use_lock_init(&mdev->use_lock);
171         mutex_init(&mdev->open_mutex);
172 
173         /* copy and truncate the name of synth device */
174         strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
175 
176         /* create MIDI coder */
177         if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
178                 pr_err("ALSA: seq_oss: can't malloc midi coder\n");
179                 kfree(mdev);
180                 return -ENOMEM;
181         }
182         /* OSS sequencer adds running status to all sequences */
183         snd_midi_event_no_status(mdev->coder, 1);
184 
185         /*
186          * look for en empty slot
187          */
188         spin_lock_irqsave(&register_lock, flags);
189         for (i = 0; i < max_midi_devs; i++) {
190                 if (midi_devs[i] == NULL)
191                         break;
192         }
193         if (i >= max_midi_devs) {
194                 if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
195                         spin_unlock_irqrestore(&register_lock, flags);
196                         snd_midi_event_free(mdev->coder);
197                         kfree(mdev);
198                         return -ENOMEM;
199                 }
200                 max_midi_devs++;
201         }
202         mdev->seq_device = i;
203         midi_devs[mdev->seq_device] = mdev;
204         spin_unlock_irqrestore(&register_lock, flags);
205 
206         return 0;
207 }
208 
209 /*
210  * release the midi device if it was registered
211  */
212 int
213 snd_seq_oss_midi_check_exit_port(int client, int port)
214 {
215         struct seq_oss_midi *mdev;
216         unsigned long flags;
217         int index;
218 
219         mdev = find_slot(client, port);
220         if (mdev) {
221                 spin_lock_irqsave(&register_lock, flags);
222                 midi_devs[mdev->seq_device] = NULL;
223                 spin_unlock_irqrestore(&register_lock, flags);
224                 snd_use_lock_free(&mdev->use_lock);
225                 snd_use_lock_sync(&mdev->use_lock);
226                 snd_midi_event_free(mdev->coder);
227                 kfree(mdev);
228         }
229         spin_lock_irqsave(&register_lock, flags);
230         for (index = max_midi_devs - 1; index >= 0; index--) {
231                 if (midi_devs[index])
232                         break;
233         }
234         max_midi_devs = index + 1;
235         spin_unlock_irqrestore(&register_lock, flags);
236         return 0;
237 }
238 
239 
240 /*
241  * release the midi device if it was registered
242  */
243 void
244 snd_seq_oss_midi_clear_all(void)
245 {
246         int i;
247         struct seq_oss_midi *mdev;
248         unsigned long flags;
249 
250         spin_lock_irqsave(&register_lock, flags);
251         for (i = 0; i < max_midi_devs; i++) {
252                 mdev = midi_devs[i];
253                 if (mdev) {
254                         snd_midi_event_free(mdev->coder);
255                         kfree(mdev);
256                         midi_devs[i] = NULL;
257                 }
258         }
259         max_midi_devs = 0;
260         spin_unlock_irqrestore(&register_lock, flags);
261 }
262 
263 
264 /*
265  * set up midi tables
266  */
267 void
268 snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
269 {
270         spin_lock_irq(&register_lock);
271         dp->max_mididev = max_midi_devs;
272         spin_unlock_irq(&register_lock);
273 }
274 
275 /*
276  * clean up midi tables
277  */
278 void
279 snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
280 {
281         int i;
282         for (i = 0; i < dp->max_mididev; i++)
283                 snd_seq_oss_midi_close(dp, i);
284         dp->max_mididev = 0;
285 }
286 
287 
288 /*
289  * open all midi devices.  ignore errors.
290  */
291 void
292 snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
293 {
294         int i;
295         for (i = 0; i < dp->max_mididev; i++)
296                 snd_seq_oss_midi_open(dp, i, file_mode);
297 }
298 
299 
300 /*
301  * get the midi device information
302  */
303 static struct seq_oss_midi *
304 get_mididev(struct seq_oss_devinfo *dp, int dev)
305 {
306         if (dev < 0 || dev >= dp->max_mididev)
307                 return NULL;
308         dev = array_index_nospec(dev, dp->max_mididev);
309         return get_mdev(dev);
310 }
311 
312 
313 /*
314  * open the midi device if not opened yet
315  */
316 int
317 snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
318 {
319         int perm;
320         struct seq_oss_midi *mdev;
321         struct snd_seq_port_subscribe subs;
322         int err;
323 
324         mdev = get_mididev(dp, dev);
325         if (!mdev)
326                 return -ENODEV;
327 
328         mutex_lock(&mdev->open_mutex);
329         /* already used? */
330         if (mdev->opened && mdev->devinfo != dp) {
331                 err = -EBUSY;
332                 goto unlock;
333         }
334 
335         perm = 0;
336         if (is_write_mode(fmode))
337                 perm |= PERM_WRITE;
338         if (is_read_mode(fmode))
339                 perm |= PERM_READ;
340         perm &= mdev->flags;
341         if (perm == 0) {
342                 err = -ENXIO;
343                 goto unlock;
344         }
345 
346         /* already opened? */
347         if ((mdev->opened & perm) == perm) {
348                 err = 0;
349                 goto unlock;
350         }
351 
352         perm &= ~mdev->opened;
353 
354         memset(&subs, 0, sizeof(subs));
355 
356         if (perm & PERM_WRITE) {
357                 subs.sender = dp->addr;
358                 subs.dest.client = mdev->client;
359                 subs.dest.port = mdev->port;
360                 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
361                         mdev->opened |= PERM_WRITE;
362         }
363         if (perm & PERM_READ) {
364                 subs.sender.client = mdev->client;
365                 subs.sender.port = mdev->port;
366                 subs.dest = dp->addr;
367                 subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
368                 subs.queue = dp->queue;         /* queue for timestamps */
369                 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
370                         mdev->opened |= PERM_READ;
371         }
372 
373         if (! mdev->opened) {
374                 err = -ENXIO;
375                 goto unlock;
376         }
377 
378         mdev->devinfo = dp;
379         err = 0;
380 
381  unlock:
382         mutex_unlock(&mdev->open_mutex);
383         snd_use_lock_free(&mdev->use_lock);
384         return err;
385 }
386 
387 /*
388  * close the midi device if already opened
389  */
390 int
391 snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
392 {
393         struct seq_oss_midi *mdev;
394         struct snd_seq_port_subscribe subs;
395 
396         mdev = get_mididev(dp, dev);
397         if (!mdev)
398                 return -ENODEV;
399         mutex_lock(&mdev->open_mutex);
400         if (!mdev->opened || mdev->devinfo != dp)
401                 goto unlock;
402 
403         memset(&subs, 0, sizeof(subs));
404         if (mdev->opened & PERM_WRITE) {
405                 subs.sender = dp->addr;
406                 subs.dest.client = mdev->client;
407                 subs.dest.port = mdev->port;
408                 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
409         }
410         if (mdev->opened & PERM_READ) {
411                 subs.sender.client = mdev->client;
412                 subs.sender.port = mdev->port;
413                 subs.dest = dp->addr;
414                 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
415         }
416 
417         mdev->opened = 0;
418         mdev->devinfo = NULL;
419 
420  unlock:
421         mutex_unlock(&mdev->open_mutex);
422         snd_use_lock_free(&mdev->use_lock);
423         return 0;
424 }
425 
426 /*
427  * change seq capability flags to file mode flags
428  */
429 int
430 snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
431 {
432         struct seq_oss_midi *mdev;
433         int mode;
434 
435         mdev = get_mididev(dp, dev);
436         if (!mdev)
437                 return 0;
438 
439         mode = 0;
440         if (mdev->opened & PERM_WRITE)
441                 mode |= SNDRV_SEQ_OSS_FILE_WRITE;
442         if (mdev->opened & PERM_READ)
443                 mode |= SNDRV_SEQ_OSS_FILE_READ;
444 
445         snd_use_lock_free(&mdev->use_lock);
446         return mode;
447 }
448 
449 /*
450  * reset the midi device and close it:
451  * so far, only close the device.
452  */
453 void
454 snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
455 {
456         struct seq_oss_midi *mdev;
457 
458         mdev = get_mididev(dp, dev);
459         if (!mdev)
460                 return;
461         if (! mdev->opened) {
462                 snd_use_lock_free(&mdev->use_lock);
463                 return;
464         }
465 
466         if (mdev->opened & PERM_WRITE) {
467                 struct snd_seq_event ev;
468                 int c;
469 
470                 memset(&ev, 0, sizeof(ev));
471                 ev.dest.client = mdev->client;
472                 ev.dest.port = mdev->port;
473                 ev.queue = dp->queue;
474                 ev.source.port = dp->port;
475                 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
476                         ev.type = SNDRV_SEQ_EVENT_SENSING;
477                         snd_seq_oss_dispatch(dp, &ev, 0, 0);
478                 }
479                 for (c = 0; c < 16; c++) {
480                         ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
481                         ev.data.control.channel = c;
482                         ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
483                         snd_seq_oss_dispatch(dp, &ev, 0, 0);
484                         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
485                                 ev.data.control.param =
486                                         MIDI_CTL_RESET_CONTROLLERS;
487                                 snd_seq_oss_dispatch(dp, &ev, 0, 0);
488                                 ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
489                                 ev.data.control.value = 0;
490                                 snd_seq_oss_dispatch(dp, &ev, 0, 0);
491                         }
492                 }
493         }
494         // snd_seq_oss_midi_close(dp, dev);
495         snd_use_lock_free(&mdev->use_lock);
496 }
497 
498 
499 /*
500  * get client/port of the specified MIDI device
501  */
502 void
503 snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
504 {
505         struct seq_oss_midi *mdev;
506 
507         mdev = get_mididev(dp, dev);
508         if (!mdev)
509                 return;
510         addr->client = mdev->client;
511         addr->port = mdev->port;
512         snd_use_lock_free(&mdev->use_lock);
513 }
514 
515 
516 /*
517  * input callback - this can be atomic
518  */
519 int
520 snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
521 {
522         struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
523         struct seq_oss_midi *mdev;
524         int rc;
525 
526         if (dp->readq == NULL)
527                 return 0;
528         mdev = find_slot(ev->source.client, ev->source.port);
529         if (!mdev)
530                 return 0;
531         if (! (mdev->opened & PERM_READ)) {
532                 snd_use_lock_free(&mdev->use_lock);
533                 return 0;
534         }
535 
536         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
537                 rc = send_synth_event(dp, ev, mdev->seq_device);
538         else
539                 rc = send_midi_event(dp, ev, mdev);
540 
541         snd_use_lock_free(&mdev->use_lock);
542         return rc;
543 }
544 
545 /*
546  * convert ALSA sequencer event to OSS synth event
547  */
548 static int
549 send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
550 {
551         union evrec ossev;
552 
553         memset(&ossev, 0, sizeof(ossev));
554 
555         switch (ev->type) {
556         case SNDRV_SEQ_EVENT_NOTEON:
557                 ossev.v.cmd = MIDI_NOTEON; break;
558         case SNDRV_SEQ_EVENT_NOTEOFF:
559                 ossev.v.cmd = MIDI_NOTEOFF; break;
560         case SNDRV_SEQ_EVENT_KEYPRESS:
561                 ossev.v.cmd = MIDI_KEY_PRESSURE; break;
562         case SNDRV_SEQ_EVENT_CONTROLLER:
563                 ossev.l.cmd = MIDI_CTL_CHANGE; break;
564         case SNDRV_SEQ_EVENT_PGMCHANGE:
565                 ossev.l.cmd = MIDI_PGM_CHANGE; break;
566         case SNDRV_SEQ_EVENT_CHANPRESS:
567                 ossev.l.cmd = MIDI_CHN_PRESSURE; break;
568         case SNDRV_SEQ_EVENT_PITCHBEND:
569                 ossev.l.cmd = MIDI_PITCH_BEND; break;
570         default:
571                 return 0; /* not supported */
572         }
573 
574         ossev.v.dev = dev;
575 
576         switch (ev->type) {
577         case SNDRV_SEQ_EVENT_NOTEON:
578         case SNDRV_SEQ_EVENT_NOTEOFF:
579         case SNDRV_SEQ_EVENT_KEYPRESS:
580                 ossev.v.code = EV_CHN_VOICE;
581                 ossev.v.note = ev->data.note.note;
582                 ossev.v.parm = ev->data.note.velocity;
583                 ossev.v.chn = ev->data.note.channel;
584                 break;
585         case SNDRV_SEQ_EVENT_CONTROLLER:
586         case SNDRV_SEQ_EVENT_PGMCHANGE:
587         case SNDRV_SEQ_EVENT_CHANPRESS:
588                 ossev.l.code = EV_CHN_COMMON;
589                 ossev.l.p1 = ev->data.control.param;
590                 ossev.l.val = ev->data.control.value;
591                 ossev.l.chn = ev->data.control.channel;
592                 break;
593         case SNDRV_SEQ_EVENT_PITCHBEND:
594                 ossev.l.code = EV_CHN_COMMON;
595                 ossev.l.val = ev->data.control.value + 8192;
596                 ossev.l.chn = ev->data.control.channel;
597                 break;
598         }
599         
600         snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
601         snd_seq_oss_readq_put_event(dp->readq, &ossev);
602 
603         return 0;
604 }
605 
606 /*
607  * decode event and send MIDI bytes to read queue
608  */
609 static int
610 send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
611 {
612         char msg[32];
613         int len;
614         
615         snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
616         if (!dp->timer->running)
617                 len = snd_seq_oss_timer_start(dp->timer);
618         if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
619                 snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev);
620                 snd_midi_event_reset_decode(mdev->coder);
621         } else {
622                 len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
623                 if (len > 0)
624                         snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len);
625         }
626 
627         return 0;
628 }
629 
630 
631 /*
632  * dump midi data
633  * return 0 : enqueued
634  *        non-zero : invalid - ignored
635  */
636 int
637 snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
638 {
639         struct seq_oss_midi *mdev;
640 
641         mdev = get_mididev(dp, dev);
642         if (!mdev)
643                 return -ENODEV;
644         if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
645                 snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
646                 snd_use_lock_free(&mdev->use_lock);
647                 return 0;
648         }
649         snd_use_lock_free(&mdev->use_lock);
650         return -EINVAL;
651 }
652 
653 /*
654  * create OSS compatible midi_info record
655  */
656 int
657 snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
658 {
659         struct seq_oss_midi *mdev;
660 
661         mdev = get_mididev(dp, dev);
662         if (!mdev)
663                 return -ENXIO;
664         inf->device = dev;
665         inf->dev_type = 0; /* FIXME: ?? */
666         inf->capabilities = 0; /* FIXME: ?? */
667         strscpy(inf->name, mdev->name, sizeof(inf->name));
668         snd_use_lock_free(&mdev->use_lock);
669         return 0;
670 }
671 
672 
673 #ifdef CONFIG_SND_PROC_FS
674 /*
675  * proc interface
676  */
677 static char *
678 capmode_str(int val)
679 {
680         val &= PERM_READ|PERM_WRITE;
681         if (val == (PERM_READ|PERM_WRITE))
682                 return "read/write";
683         else if (val == PERM_READ)
684                 return "read";
685         else if (val == PERM_WRITE)
686                 return "write";
687         else
688                 return "none";
689 }
690 
691 void
692 snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
693 {
694         int i;
695         struct seq_oss_midi *mdev;
696 
697         snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
698         for (i = 0; i < max_midi_devs; i++) {
699                 snd_iprintf(buf, "\nmidi %d: ", i);
700                 mdev = get_mdev(i);
701                 if (mdev == NULL) {
702                         snd_iprintf(buf, "*empty*\n");
703                         continue;
704                 }
705                 snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name,
706                             mdev->client, mdev->port);
707                 snd_iprintf(buf, "  capability %s / opened %s\n",
708                             capmode_str(mdev->flags),
709                             capmode_str(mdev->opened));
710                 snd_use_lock_free(&mdev->use_lock);
711         }
712 }
713 #endif /* CONFIG_SND_PROC_FS */
714 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php