seq_oss_midi.c 16 KB

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