root/sound/core/seq/oss/seq_oss_midi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_seq_oss_midi_lookup_ports
  2. get_mdev
  3. find_slot
  4. snd_seq_oss_midi_check_new_port
  5. snd_seq_oss_midi_check_exit_port
  6. snd_seq_oss_midi_clear_all
  7. snd_seq_oss_midi_setup
  8. snd_seq_oss_midi_cleanup
  9. snd_seq_oss_midi_open_all
  10. get_mididev
  11. snd_seq_oss_midi_open
  12. snd_seq_oss_midi_close
  13. snd_seq_oss_midi_filemode
  14. snd_seq_oss_midi_reset
  15. snd_seq_oss_midi_get_addr
  16. snd_seq_oss_midi_input
  17. send_synth_event
  18. send_midi_event
  19. snd_seq_oss_midi_putc
  20. snd_seq_oss_midi_make_info
  21. capmode_str
  22. snd_seq_oss_midi_info_read

   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 */

/* [<][>][^][v][top][bottom][index][help] */