Merge tag 'asoc-fix-v6.9-merge-window' of https://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / sound / core / seq / oss / seq_oss_midi.c
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 */