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