ump.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Universal MIDI Packet (UMP) support
  4. */
  5. #include <linux/list.h>
  6. #include <linux/slab.h>
  7. #include <linux/module.h>
  8. #include <linux/export.h>
  9. #include <linux/mm.h>
  10. #include <sound/core.h>
  11. #include <sound/rawmidi.h>
  12. #include <sound/ump.h>
  13. #include <sound/ump_convert.h>
  14. #define ump_err(ump, fmt, args...) dev_err((ump)->core.dev, fmt, ##args)
  15. #define ump_warn(ump, fmt, args...) dev_warn((ump)->core.dev, fmt, ##args)
  16. #define ump_info(ump, fmt, args...) dev_info((ump)->core.dev, fmt, ##args)
  17. #define ump_dbg(ump, fmt, args...) dev_dbg((ump)->core.dev, fmt, ##args)
  18. static int snd_ump_dev_register(struct snd_rawmidi *rmidi);
  19. static int snd_ump_dev_unregister(struct snd_rawmidi *rmidi);
  20. static long snd_ump_ioctl(struct snd_rawmidi *rmidi, unsigned int cmd,
  21. void __user *argp);
  22. static void snd_ump_proc_read(struct snd_info_entry *entry,
  23. struct snd_info_buffer *buffer);
  24. static int snd_ump_rawmidi_open(struct snd_rawmidi_substream *substream);
  25. static int snd_ump_rawmidi_close(struct snd_rawmidi_substream *substream);
  26. static void snd_ump_rawmidi_trigger(struct snd_rawmidi_substream *substream,
  27. int up);
  28. static void snd_ump_rawmidi_drain(struct snd_rawmidi_substream *substream);
  29. static void ump_handle_stream_msg(struct snd_ump_endpoint *ump,
  30. const u32 *buf, int size);
  31. #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
  32. static int process_legacy_output(struct snd_ump_endpoint *ump,
  33. u32 *buffer, int count);
  34. static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
  35. int words);
  36. static void update_legacy_names(struct snd_ump_endpoint *ump);
  37. #else
  38. static inline int process_legacy_output(struct snd_ump_endpoint *ump,
  39. u32 *buffer, int count)
  40. {
  41. return 0;
  42. }
  43. static inline void process_legacy_input(struct snd_ump_endpoint *ump,
  44. const u32 *src, int words)
  45. {
  46. }
  47. static inline void update_legacy_names(struct snd_ump_endpoint *ump)
  48. {
  49. }
  50. #endif
  51. static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = {
  52. .dev_register = snd_ump_dev_register,
  53. .dev_unregister = snd_ump_dev_unregister,
  54. .ioctl = snd_ump_ioctl,
  55. .proc_read = snd_ump_proc_read,
  56. };
  57. static const struct snd_rawmidi_ops snd_ump_rawmidi_input_ops = {
  58. .open = snd_ump_rawmidi_open,
  59. .close = snd_ump_rawmidi_close,
  60. .trigger = snd_ump_rawmidi_trigger,
  61. };
  62. static const struct snd_rawmidi_ops snd_ump_rawmidi_output_ops = {
  63. .open = snd_ump_rawmidi_open,
  64. .close = snd_ump_rawmidi_close,
  65. .trigger = snd_ump_rawmidi_trigger,
  66. .drain = snd_ump_rawmidi_drain,
  67. };
  68. static void snd_ump_endpoint_free(struct snd_rawmidi *rmidi)
  69. {
  70. struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
  71. struct snd_ump_block *fb;
  72. while (!list_empty(&ump->block_list)) {
  73. fb = list_first_entry(&ump->block_list, struct snd_ump_block,
  74. list);
  75. list_del(&fb->list);
  76. if (fb->private_free)
  77. fb->private_free(fb);
  78. kfree(fb);
  79. }
  80. if (ump->private_free)
  81. ump->private_free(ump);
  82. #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
  83. kfree(ump->out_cvts);
  84. #endif
  85. }
  86. /**
  87. * snd_ump_endpoint_new - create a UMP Endpoint object
  88. * @card: the card instance
  89. * @id: the id string for rawmidi
  90. * @device: the device index for rawmidi
  91. * @output: 1 for enabling output
  92. * @input: 1 for enabling input
  93. * @ump_ret: the pointer to store the new UMP instance
  94. *
  95. * Creates a new UMP Endpoint object. A UMP Endpoint is tied with one rawmidi
  96. * instance with one input and/or one output rawmidi stream (either uni-
  97. * or bi-directional). A UMP Endpoint may contain one or multiple UMP Blocks
  98. * that consist of one or multiple UMP Groups.
  99. *
  100. * Use snd_rawmidi_set_ops() to set the operators to the new instance.
  101. * Unlike snd_rawmidi_new(), this function sets up the info_flags by itself
  102. * depending on the given @output and @input.
  103. *
  104. * The device has SNDRV_RAWMIDI_INFO_UMP flag set and a different device
  105. * file ("umpCxDx") than a standard MIDI 1.x device ("midiCxDx") is
  106. * created.
  107. *
  108. * Return: Zero if successful, or a negative error code on failure.
  109. */
  110. int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
  111. int output, int input,
  112. struct snd_ump_endpoint **ump_ret)
  113. {
  114. unsigned int info_flags = SNDRV_RAWMIDI_INFO_UMP;
  115. struct snd_ump_endpoint *ump;
  116. int err;
  117. if (input)
  118. info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  119. if (output)
  120. info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  121. if (input && output)
  122. info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  123. ump = kzalloc(sizeof(*ump), GFP_KERNEL);
  124. if (!ump)
  125. return -ENOMEM;
  126. INIT_LIST_HEAD(&ump->block_list);
  127. mutex_init(&ump->open_mutex);
  128. init_waitqueue_head(&ump->stream_wait);
  129. #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
  130. spin_lock_init(&ump->legacy_locks[0]);
  131. spin_lock_init(&ump->legacy_locks[1]);
  132. #endif
  133. err = snd_rawmidi_init(&ump->core, card, id, device,
  134. output, input, info_flags);
  135. if (err < 0) {
  136. snd_rawmidi_free(&ump->core);
  137. return err;
  138. }
  139. ump->info.card = card->number;
  140. ump->info.device = device;
  141. ump->core.private_free = snd_ump_endpoint_free;
  142. ump->core.ops = &snd_ump_rawmidi_ops;
  143. if (input)
  144. snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_INPUT,
  145. &snd_ump_rawmidi_input_ops);
  146. if (output)
  147. snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_OUTPUT,
  148. &snd_ump_rawmidi_output_ops);
  149. ump_dbg(ump, "Created a UMP EP #%d (%s)\n", device, id);
  150. *ump_ret = ump;
  151. return 0;
  152. }
  153. EXPORT_SYMBOL_GPL(snd_ump_endpoint_new);
  154. /*
  155. * Device register / unregister hooks;
  156. * do nothing, placeholders for avoiding the default rawmidi handling
  157. */
  158. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  159. static void snd_ump_dev_seq_free(struct snd_seq_device *device)
  160. {
  161. struct snd_ump_endpoint *ump = device->private_data;
  162. ump->seq_dev = NULL;
  163. }
  164. #endif
  165. static int snd_ump_dev_register(struct snd_rawmidi *rmidi)
  166. {
  167. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  168. struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
  169. int err;
  170. err = snd_seq_device_new(ump->core.card, ump->core.device,
  171. SNDRV_SEQ_DEV_ID_UMP, 0, &ump->seq_dev);
  172. if (err < 0)
  173. return err;
  174. ump->seq_dev->private_data = ump;
  175. ump->seq_dev->private_free = snd_ump_dev_seq_free;
  176. snd_device_register(ump->core.card, ump->seq_dev);
  177. #endif
  178. return 0;
  179. }
  180. static int snd_ump_dev_unregister(struct snd_rawmidi *rmidi)
  181. {
  182. return 0;
  183. }
  184. static struct snd_ump_block *
  185. snd_ump_get_block(struct snd_ump_endpoint *ump, unsigned char id)
  186. {
  187. struct snd_ump_block *fb;
  188. list_for_each_entry(fb, &ump->block_list, list) {
  189. if (fb->info.block_id == id)
  190. return fb;
  191. }
  192. return NULL;
  193. }
  194. /*
  195. * rawmidi ops for UMP endpoint
  196. */
  197. static int snd_ump_rawmidi_open(struct snd_rawmidi_substream *substream)
  198. {
  199. struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
  200. int dir = substream->stream;
  201. int err;
  202. if (ump->substreams[dir])
  203. return -EBUSY;
  204. err = ump->ops->open(ump, dir);
  205. if (err < 0)
  206. return err;
  207. ump->substreams[dir] = substream;
  208. return 0;
  209. }
  210. static int snd_ump_rawmidi_close(struct snd_rawmidi_substream *substream)
  211. {
  212. struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
  213. int dir = substream->stream;
  214. ump->substreams[dir] = NULL;
  215. ump->ops->close(ump, dir);
  216. return 0;
  217. }
  218. static void snd_ump_rawmidi_trigger(struct snd_rawmidi_substream *substream,
  219. int up)
  220. {
  221. struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
  222. int dir = substream->stream;
  223. ump->ops->trigger(ump, dir, up);
  224. }
  225. static void snd_ump_rawmidi_drain(struct snd_rawmidi_substream *substream)
  226. {
  227. struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
  228. if (ump->ops->drain)
  229. ump->ops->drain(ump, SNDRV_RAWMIDI_STREAM_OUTPUT);
  230. }
  231. /* number of 32bit words per message type */
  232. static unsigned char ump_packet_words[0x10] = {
  233. 1, 1, 1, 2, 2, 4, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4
  234. };
  235. /**
  236. * snd_ump_receive_ump_val - parse the UMP packet data
  237. * @ump: UMP endpoint
  238. * @val: UMP packet data
  239. *
  240. * The data is copied onto ump->input_buf[].
  241. * When a full packet is completed, returns the number of words (from 1 to 4).
  242. * OTOH, if the packet is incomplete, returns 0.
  243. */
  244. int snd_ump_receive_ump_val(struct snd_ump_endpoint *ump, u32 val)
  245. {
  246. int words;
  247. if (!ump->input_pending)
  248. ump->input_pending = ump_packet_words[ump_message_type(val)];
  249. ump->input_buf[ump->input_buf_head++] = val;
  250. ump->input_pending--;
  251. if (!ump->input_pending) {
  252. words = ump->input_buf_head;
  253. ump->input_buf_head = 0;
  254. return words;
  255. }
  256. return 0;
  257. }
  258. EXPORT_SYMBOL_GPL(snd_ump_receive_ump_val);
  259. /**
  260. * snd_ump_receive - transfer UMP packets from the device
  261. * @ump: the UMP endpoint
  262. * @buffer: the buffer pointer to transfer
  263. * @count: byte size to transfer
  264. *
  265. * Called from the driver to submit the received UMP packets from the device
  266. * to user-space. It's essentially a wrapper of rawmidi_receive().
  267. * The data to receive is in CPU-native endianness.
  268. */
  269. int snd_ump_receive(struct snd_ump_endpoint *ump, const u32 *buffer, int count)
  270. {
  271. struct snd_rawmidi_substream *substream;
  272. const u32 *p = buffer;
  273. int n, words = count >> 2;
  274. while (words--) {
  275. n = snd_ump_receive_ump_val(ump, *p++);
  276. if (!n)
  277. continue;
  278. ump_handle_stream_msg(ump, ump->input_buf, n);
  279. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  280. if (ump->seq_ops)
  281. ump->seq_ops->input_receive(ump, ump->input_buf, n);
  282. #endif
  283. process_legacy_input(ump, ump->input_buf, n);
  284. }
  285. substream = ump->substreams[SNDRV_RAWMIDI_STREAM_INPUT];
  286. if (!substream)
  287. return 0;
  288. return snd_rawmidi_receive(substream, (const char *)buffer, count);
  289. }
  290. EXPORT_SYMBOL_GPL(snd_ump_receive);
  291. /**
  292. * snd_ump_transmit - transmit UMP packets
  293. * @ump: the UMP endpoint
  294. * @buffer: the buffer pointer to transfer
  295. * @count: byte size to transfer
  296. *
  297. * Called from the driver to obtain the UMP packets from user-space to the
  298. * device. It's essentially a wrapper of rawmidi_transmit().
  299. * The data to transmit is in CPU-native endianness.
  300. */
  301. int snd_ump_transmit(struct snd_ump_endpoint *ump, u32 *buffer, int count)
  302. {
  303. struct snd_rawmidi_substream *substream =
  304. ump->substreams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  305. int err;
  306. if (!substream)
  307. return -ENODEV;
  308. err = snd_rawmidi_transmit(substream, (char *)buffer, count);
  309. /* received either data or an error? */
  310. if (err)
  311. return err;
  312. return process_legacy_output(ump, buffer, count);
  313. }
  314. EXPORT_SYMBOL_GPL(snd_ump_transmit);
  315. /**
  316. * snd_ump_block_new - Create a UMP block
  317. * @ump: UMP object
  318. * @blk: block ID number to create
  319. * @direction: direction (in/out/bidirection)
  320. * @first_group: the first group ID (0-based)
  321. * @num_groups: the number of groups in this block
  322. * @blk_ret: the pointer to store the resultant block object
  323. */
  324. int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
  325. unsigned int direction, unsigned int first_group,
  326. unsigned int num_groups, struct snd_ump_block **blk_ret)
  327. {
  328. struct snd_ump_block *fb, *p;
  329. if (blk < 0 || blk >= SNDRV_UMP_MAX_BLOCKS)
  330. return -EINVAL;
  331. if (snd_ump_get_block(ump, blk))
  332. return -EBUSY;
  333. fb = kzalloc(sizeof(*fb), GFP_KERNEL);
  334. if (!fb)
  335. return -ENOMEM;
  336. fb->ump = ump;
  337. fb->info.card = ump->info.card;
  338. fb->info.device = ump->info.device;
  339. fb->info.block_id = blk;
  340. if (blk >= ump->info.num_blocks)
  341. ump->info.num_blocks = blk + 1;
  342. fb->info.direction = direction;
  343. fb->info.active = 1;
  344. fb->info.first_group = first_group;
  345. fb->info.num_groups = num_groups;
  346. /* fill the default name, may be overwritten to a better name */
  347. snprintf(fb->info.name, sizeof(fb->info.name), "Group %d-%d",
  348. first_group + 1, first_group + num_groups);
  349. /* put the entry in the ordered list */
  350. list_for_each_entry(p, &ump->block_list, list) {
  351. if (p->info.block_id > blk) {
  352. list_add_tail(&fb->list, &p->list);
  353. goto added;
  354. }
  355. }
  356. list_add_tail(&fb->list, &ump->block_list);
  357. added:
  358. ump_dbg(ump, "Created a UMP Block #%d (%s)\n", blk, fb->info.name);
  359. *blk_ret = fb;
  360. return 0;
  361. }
  362. EXPORT_SYMBOL_GPL(snd_ump_block_new);
  363. static int snd_ump_ioctl_block(struct snd_ump_endpoint *ump,
  364. struct snd_ump_block_info __user *argp)
  365. {
  366. struct snd_ump_block *fb;
  367. unsigned char id;
  368. if (get_user(id, &argp->block_id))
  369. return -EFAULT;
  370. fb = snd_ump_get_block(ump, id);
  371. if (!fb)
  372. return -ENOENT;
  373. if (copy_to_user(argp, &fb->info, sizeof(fb->info)))
  374. return -EFAULT;
  375. return 0;
  376. }
  377. /*
  378. * Handle UMP-specific ioctls; called from snd_rawmidi_ioctl()
  379. */
  380. static long snd_ump_ioctl(struct snd_rawmidi *rmidi, unsigned int cmd,
  381. void __user *argp)
  382. {
  383. struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
  384. switch (cmd) {
  385. case SNDRV_UMP_IOCTL_ENDPOINT_INFO:
  386. if (copy_to_user(argp, &ump->info, sizeof(ump->info)))
  387. return -EFAULT;
  388. return 0;
  389. case SNDRV_UMP_IOCTL_BLOCK_INFO:
  390. return snd_ump_ioctl_block(ump, argp);
  391. default:
  392. ump_dbg(ump, "rawmidi: unknown command = 0x%x\n", cmd);
  393. return -ENOTTY;
  394. }
  395. }
  396. static const char *ump_direction_string(int dir)
  397. {
  398. switch (dir) {
  399. case SNDRV_UMP_DIR_INPUT:
  400. return "input";
  401. case SNDRV_UMP_DIR_OUTPUT:
  402. return "output";
  403. case SNDRV_UMP_DIR_BIDIRECTION:
  404. return "bidirection";
  405. default:
  406. return "unknown";
  407. }
  408. }
  409. static const char *ump_ui_hint_string(int dir)
  410. {
  411. switch (dir) {
  412. case SNDRV_UMP_BLOCK_UI_HINT_RECEIVER:
  413. return "receiver";
  414. case SNDRV_UMP_BLOCK_UI_HINT_SENDER:
  415. return "sender";
  416. case SNDRV_UMP_BLOCK_UI_HINT_BOTH:
  417. return "both";
  418. default:
  419. return "unknown";
  420. }
  421. }
  422. /* Additional proc file output */
  423. static void snd_ump_proc_read(struct snd_info_entry *entry,
  424. struct snd_info_buffer *buffer)
  425. {
  426. struct snd_rawmidi *rmidi = entry->private_data;
  427. struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
  428. struct snd_ump_block *fb;
  429. snd_iprintf(buffer, "EP Name: %s\n", ump->info.name);
  430. snd_iprintf(buffer, "EP Product ID: %s\n", ump->info.product_id);
  431. snd_iprintf(buffer, "UMP Version: 0x%04x\n", ump->info.version);
  432. snd_iprintf(buffer, "Protocol Caps: 0x%08x\n", ump->info.protocol_caps);
  433. snd_iprintf(buffer, "Protocol: 0x%08x\n", ump->info.protocol);
  434. if (ump->info.version) {
  435. snd_iprintf(buffer, "Manufacturer ID: 0x%08x\n",
  436. ump->info.manufacturer_id);
  437. snd_iprintf(buffer, "Family ID: 0x%04x\n", ump->info.family_id);
  438. snd_iprintf(buffer, "Model ID: 0x%04x\n", ump->info.model_id);
  439. snd_iprintf(buffer, "SW Revision: 0x%4phN\n", ump->info.sw_revision);
  440. }
  441. snd_iprintf(buffer, "Static Blocks: %s\n",
  442. (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) ? "Yes" : "No");
  443. snd_iprintf(buffer, "Num Blocks: %d\n\n", ump->info.num_blocks);
  444. list_for_each_entry(fb, &ump->block_list, list) {
  445. snd_iprintf(buffer, "Block %d (%s)\n", fb->info.block_id,
  446. fb->info.name);
  447. snd_iprintf(buffer, " Direction: %s\n",
  448. ump_direction_string(fb->info.direction));
  449. snd_iprintf(buffer, " Active: %s\n",
  450. fb->info.active ? "Yes" : "No");
  451. snd_iprintf(buffer, " Groups: %d-%d\n",
  452. fb->info.first_group + 1,
  453. fb->info.first_group + fb->info.num_groups);
  454. snd_iprintf(buffer, " Is MIDI1: %s%s\n",
  455. (fb->info.flags & SNDRV_UMP_BLOCK_IS_MIDI1) ? "Yes" : "No",
  456. (fb->info.flags & SNDRV_UMP_BLOCK_IS_LOWSPEED) ? " (Low Speed)" : "");
  457. if (ump->info.version) {
  458. snd_iprintf(buffer, " MIDI-CI Version: %d\n",
  459. fb->info.midi_ci_version);
  460. snd_iprintf(buffer, " Sysex8 Streams: %d\n",
  461. fb->info.sysex8_streams);
  462. snd_iprintf(buffer, " UI Hint: %s\n",
  463. ump_ui_hint_string(fb->info.ui_hint));
  464. }
  465. snd_iprintf(buffer, "\n");
  466. }
  467. }
  468. /* update dir_bits and active flag for all groups in the client */
  469. void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump)
  470. {
  471. struct snd_ump_block *fb;
  472. struct snd_ump_group *group;
  473. int i;
  474. for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
  475. group = &ump->groups[i];
  476. *group->name = 0;
  477. group->dir_bits = 0;
  478. group->active = 0;
  479. group->group = i;
  480. group->valid = false;
  481. group->is_midi1 = false;
  482. }
  483. list_for_each_entry(fb, &ump->block_list, list) {
  484. if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
  485. break;
  486. group = &ump->groups[fb->info.first_group];
  487. for (i = 0; i < fb->info.num_groups; i++, group++) {
  488. group->valid = true;
  489. if (fb->info.active)
  490. group->active = 1;
  491. if (fb->info.flags & SNDRV_UMP_BLOCK_IS_MIDI1)
  492. group->is_midi1 = true;
  493. switch (fb->info.direction) {
  494. case SNDRV_UMP_DIR_INPUT:
  495. group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT);
  496. break;
  497. case SNDRV_UMP_DIR_OUTPUT:
  498. group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
  499. break;
  500. case SNDRV_UMP_DIR_BIDIRECTION:
  501. group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT) |
  502. (1 << SNDRV_RAWMIDI_STREAM_OUTPUT);
  503. break;
  504. }
  505. if (!*fb->info.name)
  506. continue;
  507. if (!*group->name) {
  508. /* store the first matching name */
  509. strscpy(group->name, fb->info.name,
  510. sizeof(group->name));
  511. } else {
  512. /* when overlapping, concat names */
  513. strlcat(group->name, ", ", sizeof(group->name));
  514. strlcat(group->name, fb->info.name,
  515. sizeof(group->name));
  516. }
  517. }
  518. }
  519. }
  520. EXPORT_SYMBOL_GPL(snd_ump_update_group_attrs);
  521. /*
  522. * UMP endpoint and function block handling
  523. */
  524. /* open / close UMP streams for the internal stream msg communication */
  525. static int ump_request_open(struct snd_ump_endpoint *ump)
  526. {
  527. return snd_rawmidi_kernel_open(&ump->core, 0,
  528. SNDRV_RAWMIDI_LFLG_OUTPUT,
  529. &ump->stream_rfile);
  530. }
  531. static void ump_request_close(struct snd_ump_endpoint *ump)
  532. {
  533. snd_rawmidi_kernel_release(&ump->stream_rfile);
  534. }
  535. /* request a command and wait for the given response;
  536. * @req1 and @req2 are u32 commands
  537. * @reply is the expected UMP stream status
  538. */
  539. static int ump_req_msg(struct snd_ump_endpoint *ump, u32 req1, u32 req2,
  540. u32 reply)
  541. {
  542. u32 buf[4];
  543. ump_dbg(ump, "%s: request %08x %08x, wait-for %08x\n",
  544. __func__, req1, req2, reply);
  545. memset(buf, 0, sizeof(buf));
  546. buf[0] = req1;
  547. buf[1] = req2;
  548. ump->stream_finished = 0;
  549. ump->stream_wait_for = reply;
  550. snd_rawmidi_kernel_write(ump->stream_rfile.output,
  551. (unsigned char *)&buf, 16);
  552. wait_event_timeout(ump->stream_wait, ump->stream_finished,
  553. msecs_to_jiffies(500));
  554. if (!READ_ONCE(ump->stream_finished)) {
  555. ump_dbg(ump, "%s: request timed out\n", __func__);
  556. return -ETIMEDOUT;
  557. }
  558. ump->stream_finished = 0;
  559. ump_dbg(ump, "%s: reply: %08x %08x %08x %08x\n",
  560. __func__, buf[0], buf[1], buf[2], buf[3]);
  561. return 0;
  562. }
  563. /* append the received letters via UMP packet to the given string buffer;
  564. * return 1 if the full string is received or 0 to continue
  565. */
  566. static int ump_append_string(struct snd_ump_endpoint *ump, char *dest,
  567. int maxsize, const u32 *buf, int offset)
  568. {
  569. unsigned char format;
  570. int c;
  571. format = ump_stream_message_format(buf[0]);
  572. if (format == UMP_STREAM_MSG_FORMAT_SINGLE ||
  573. format == UMP_STREAM_MSG_FORMAT_START) {
  574. c = 0;
  575. } else {
  576. c = strlen(dest);
  577. if (c >= maxsize - 1)
  578. return 1;
  579. }
  580. for (; offset < 16; offset++) {
  581. dest[c] = buf[offset / 4] >> (3 - (offset % 4)) * 8;
  582. if (!dest[c])
  583. break;
  584. if (++c >= maxsize - 1)
  585. break;
  586. }
  587. dest[c] = 0;
  588. return (format == UMP_STREAM_MSG_FORMAT_SINGLE ||
  589. format == UMP_STREAM_MSG_FORMAT_END);
  590. }
  591. /* Choose the default protocol */
  592. static void choose_default_protocol(struct snd_ump_endpoint *ump)
  593. {
  594. if (ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK)
  595. return;
  596. if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2)
  597. ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI2;
  598. else
  599. ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1;
  600. }
  601. /* handle EP info stream message; update the UMP attributes */
  602. static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump,
  603. const union snd_ump_stream_msg *buf)
  604. {
  605. ump->info.version = (buf->ep_info.ump_version_major << 8) |
  606. buf->ep_info.ump_version_minor;
  607. ump->info.num_blocks = buf->ep_info.num_function_blocks;
  608. if (ump->info.num_blocks > SNDRV_UMP_MAX_BLOCKS) {
  609. ump_info(ump, "Invalid function blocks %d, fallback to 1\n",
  610. ump->info.num_blocks);
  611. ump->info.num_blocks = 1;
  612. }
  613. if (buf->ep_info.static_function_block)
  614. ump->info.flags |= SNDRV_UMP_EP_INFO_STATIC_BLOCKS;
  615. ump->info.protocol_caps = (buf->ep_info.protocol << 8) |
  616. buf->ep_info.jrts;
  617. ump_dbg(ump, "EP info: version=%x, num_blocks=%x, proto_caps=%x\n",
  618. ump->info.version, ump->info.num_blocks, ump->info.protocol_caps);
  619. ump->info.protocol &= ump->info.protocol_caps;
  620. choose_default_protocol(ump);
  621. return 1; /* finished */
  622. }
  623. /* handle EP device info stream message; update the UMP attributes */
  624. static int ump_handle_device_info_msg(struct snd_ump_endpoint *ump,
  625. const union snd_ump_stream_msg *buf)
  626. {
  627. ump->info.manufacturer_id = buf->device_info.manufacture_id & 0x7f7f7f;
  628. ump->info.family_id = (buf->device_info.family_msb << 8) |
  629. buf->device_info.family_lsb;
  630. ump->info.model_id = (buf->device_info.model_msb << 8) |
  631. buf->device_info.model_lsb;
  632. ump->info.sw_revision[0] = (buf->device_info.sw_revision >> 24) & 0x7f;
  633. ump->info.sw_revision[1] = (buf->device_info.sw_revision >> 16) & 0x7f;
  634. ump->info.sw_revision[2] = (buf->device_info.sw_revision >> 8) & 0x7f;
  635. ump->info.sw_revision[3] = buf->device_info.sw_revision & 0x7f;
  636. ump_dbg(ump, "EP devinfo: manid=%08x, family=%04x, model=%04x, sw=%4phN\n",
  637. ump->info.manufacturer_id,
  638. ump->info.family_id,
  639. ump->info.model_id,
  640. ump->info.sw_revision);
  641. return 1; /* finished */
  642. }
  643. /* handle EP name stream message; update the UMP name string */
  644. static int ump_handle_ep_name_msg(struct snd_ump_endpoint *ump,
  645. const union snd_ump_stream_msg *buf)
  646. {
  647. return ump_append_string(ump, ump->info.name, sizeof(ump->info.name),
  648. buf->raw, 2);
  649. }
  650. /* handle EP product id stream message; update the UMP product_id string */
  651. static int ump_handle_product_id_msg(struct snd_ump_endpoint *ump,
  652. const union snd_ump_stream_msg *buf)
  653. {
  654. return ump_append_string(ump, ump->info.product_id,
  655. sizeof(ump->info.product_id),
  656. buf->raw, 2);
  657. }
  658. /* notify the protocol change to sequencer */
  659. static void seq_notify_protocol(struct snd_ump_endpoint *ump)
  660. {
  661. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  662. if (ump->seq_ops && ump->seq_ops->switch_protocol)
  663. ump->seq_ops->switch_protocol(ump);
  664. #endif /* CONFIG_SND_SEQUENCER */
  665. }
  666. /**
  667. * snd_ump_switch_protocol - switch MIDI protocol
  668. * @ump: UMP endpoint
  669. * @protocol: protocol to switch to
  670. *
  671. * Returns 1 if the protocol is actually switched, 0 if unchanged
  672. */
  673. int snd_ump_switch_protocol(struct snd_ump_endpoint *ump, unsigned int protocol)
  674. {
  675. unsigned int type;
  676. protocol &= ump->info.protocol_caps;
  677. if (protocol == ump->info.protocol)
  678. return 0;
  679. type = protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK;
  680. if (type != SNDRV_UMP_EP_INFO_PROTO_MIDI1 &&
  681. type != SNDRV_UMP_EP_INFO_PROTO_MIDI2)
  682. return 0;
  683. ump->info.protocol = protocol;
  684. ump_dbg(ump, "New protocol = %x (caps = %x)\n",
  685. protocol, ump->info.protocol_caps);
  686. seq_notify_protocol(ump);
  687. return 1;
  688. }
  689. EXPORT_SYMBOL_GPL(snd_ump_switch_protocol);
  690. /* handle EP stream config message; update the UMP protocol */
  691. static int ump_handle_stream_cfg_msg(struct snd_ump_endpoint *ump,
  692. const union snd_ump_stream_msg *buf)
  693. {
  694. unsigned int protocol =
  695. (buf->stream_cfg.protocol << 8) | buf->stream_cfg.jrts;
  696. snd_ump_switch_protocol(ump, protocol);
  697. return 1; /* finished */
  698. }
  699. /* Extract Function Block info from UMP packet */
  700. static void fill_fb_info(struct snd_ump_endpoint *ump,
  701. struct snd_ump_block_info *info,
  702. const union snd_ump_stream_msg *buf)
  703. {
  704. info->direction = buf->fb_info.direction;
  705. info->ui_hint = buf->fb_info.ui_hint;
  706. info->first_group = buf->fb_info.first_group;
  707. info->num_groups = buf->fb_info.num_groups;
  708. if (buf->fb_info.midi_10 < 2)
  709. info->flags = buf->fb_info.midi_10;
  710. else
  711. info->flags = SNDRV_UMP_BLOCK_IS_MIDI1 | SNDRV_UMP_BLOCK_IS_LOWSPEED;
  712. info->active = buf->fb_info.active;
  713. info->midi_ci_version = buf->fb_info.midi_ci_version;
  714. info->sysex8_streams = buf->fb_info.sysex8_streams;
  715. ump_dbg(ump, "FB %d: dir=%d, active=%d, first_gp=%d, num_gp=%d, midici=%d, sysex8=%d, flags=0x%x\n",
  716. info->block_id, info->direction, info->active,
  717. info->first_group, info->num_groups, info->midi_ci_version,
  718. info->sysex8_streams, info->flags);
  719. if ((info->flags & SNDRV_UMP_BLOCK_IS_MIDI1) && info->num_groups != 1) {
  720. info->num_groups = 1;
  721. ump_dbg(ump, "FB %d: corrected groups to 1 for MIDI1\n",
  722. info->block_id);
  723. }
  724. }
  725. /* check whether the FB info gets updated by the current message */
  726. static bool is_fb_info_updated(struct snd_ump_endpoint *ump,
  727. struct snd_ump_block *fb,
  728. const union snd_ump_stream_msg *buf)
  729. {
  730. char tmpbuf[offsetof(struct snd_ump_block_info, name)];
  731. if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) {
  732. ump_info(ump, "Skipping static FB info update (blk#%d)\n",
  733. fb->info.block_id);
  734. return 0;
  735. }
  736. memcpy(tmpbuf, &fb->info, sizeof(tmpbuf));
  737. fill_fb_info(ump, (struct snd_ump_block_info *)tmpbuf, buf);
  738. return memcmp(&fb->info, tmpbuf, sizeof(tmpbuf)) != 0;
  739. }
  740. /* notify the FB info/name change to sequencer */
  741. static void seq_notify_fb_change(struct snd_ump_endpoint *ump,
  742. struct snd_ump_block *fb)
  743. {
  744. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  745. if (ump->seq_ops && ump->seq_ops->notify_fb_change)
  746. ump->seq_ops->notify_fb_change(ump, fb);
  747. #endif
  748. }
  749. /* handle FB info message; update FB info if the block is present */
  750. static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
  751. const union snd_ump_stream_msg *buf)
  752. {
  753. unsigned char blk;
  754. struct snd_ump_block *fb;
  755. blk = buf->fb_info.function_block_id;
  756. fb = snd_ump_get_block(ump, blk);
  757. /* complain only if updated after parsing */
  758. if (!fb && ump->parsed) {
  759. ump_info(ump, "Function Block Info Update for non-existing block %d\n",
  760. blk);
  761. return -ENODEV;
  762. }
  763. /* When updated after the initial parse, check the FB info update */
  764. if (ump->parsed && !is_fb_info_updated(ump, fb, buf))
  765. return 1; /* no content change */
  766. if (fb) {
  767. fill_fb_info(ump, &fb->info, buf);
  768. if (ump->parsed) {
  769. snd_ump_update_group_attrs(ump);
  770. update_legacy_names(ump);
  771. seq_notify_fb_change(ump, fb);
  772. }
  773. }
  774. return 1; /* finished */
  775. }
  776. /* handle FB name message; update the FB name string */
  777. static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump,
  778. const union snd_ump_stream_msg *buf)
  779. {
  780. unsigned char blk;
  781. struct snd_ump_block *fb;
  782. int ret;
  783. blk = buf->fb_name.function_block_id;
  784. fb = snd_ump_get_block(ump, blk);
  785. if (!fb)
  786. return -ENODEV;
  787. if (ump->parsed &&
  788. (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS)) {
  789. ump_dbg(ump, "Skipping static FB name update (blk#%d)\n",
  790. fb->info.block_id);
  791. return 0;
  792. }
  793. ret = ump_append_string(ump, fb->info.name, sizeof(fb->info.name),
  794. buf->raw, 3);
  795. /* notify the FB name update to sequencer, too */
  796. if (ret > 0 && ump->parsed) {
  797. snd_ump_update_group_attrs(ump);
  798. update_legacy_names(ump);
  799. seq_notify_fb_change(ump, fb);
  800. }
  801. return ret;
  802. }
  803. static int create_block_from_fb_info(struct snd_ump_endpoint *ump, int blk)
  804. {
  805. struct snd_ump_block *fb;
  806. unsigned char direction, first_group, num_groups;
  807. const union snd_ump_stream_msg *buf =
  808. (const union snd_ump_stream_msg *)ump->input_buf;
  809. u32 msg;
  810. int err;
  811. /* query the FB info once */
  812. msg = ump_stream_compose(UMP_STREAM_MSG_STATUS_FB_DISCOVERY, 0) |
  813. (blk << 8) | UMP_STREAM_MSG_REQUEST_FB_INFO;
  814. err = ump_req_msg(ump, msg, 0, UMP_STREAM_MSG_STATUS_FB_INFO);
  815. if (err < 0) {
  816. ump_dbg(ump, "Unable to get FB info for block %d\n", blk);
  817. return err;
  818. }
  819. /* the last input must be the FB info */
  820. if (buf->fb_info.status != UMP_STREAM_MSG_STATUS_FB_INFO) {
  821. ump_dbg(ump, "Inconsistent input: 0x%x\n", *buf->raw);
  822. return -EINVAL;
  823. }
  824. direction = buf->fb_info.direction;
  825. first_group = buf->fb_info.first_group;
  826. num_groups = buf->fb_info.num_groups;
  827. err = snd_ump_block_new(ump, blk, direction, first_group, num_groups,
  828. &fb);
  829. if (err < 0)
  830. return err;
  831. fill_fb_info(ump, &fb->info, buf);
  832. msg = ump_stream_compose(UMP_STREAM_MSG_STATUS_FB_DISCOVERY, 0) |
  833. (blk << 8) | UMP_STREAM_MSG_REQUEST_FB_NAME;
  834. err = ump_req_msg(ump, msg, 0, UMP_STREAM_MSG_STATUS_FB_NAME);
  835. if (err)
  836. ump_dbg(ump, "Unable to get UMP FB name string #%d\n", blk);
  837. return 0;
  838. }
  839. /* handle stream messages, called from snd_ump_receive() */
  840. static void ump_handle_stream_msg(struct snd_ump_endpoint *ump,
  841. const u32 *buf, int size)
  842. {
  843. const union snd_ump_stream_msg *msg;
  844. unsigned int status;
  845. int ret;
  846. /* UMP stream message suppressed (for gadget UMP)? */
  847. if (ump->no_process_stream)
  848. return;
  849. BUILD_BUG_ON(sizeof(*msg) != 16);
  850. ump_dbg(ump, "Stream msg: %08x %08x %08x %08x\n",
  851. buf[0], buf[1], buf[2], buf[3]);
  852. if (size != 4 || ump_message_type(*buf) != UMP_MSG_TYPE_STREAM)
  853. return;
  854. msg = (const union snd_ump_stream_msg *)buf;
  855. status = ump_stream_message_status(*buf);
  856. switch (status) {
  857. case UMP_STREAM_MSG_STATUS_EP_INFO:
  858. ret = ump_handle_ep_info_msg(ump, msg);
  859. break;
  860. case UMP_STREAM_MSG_STATUS_DEVICE_INFO:
  861. ret = ump_handle_device_info_msg(ump, msg);
  862. break;
  863. case UMP_STREAM_MSG_STATUS_EP_NAME:
  864. ret = ump_handle_ep_name_msg(ump, msg);
  865. break;
  866. case UMP_STREAM_MSG_STATUS_PRODUCT_ID:
  867. ret = ump_handle_product_id_msg(ump, msg);
  868. break;
  869. case UMP_STREAM_MSG_STATUS_STREAM_CFG:
  870. ret = ump_handle_stream_cfg_msg(ump, msg);
  871. break;
  872. case UMP_STREAM_MSG_STATUS_FB_INFO:
  873. ret = ump_handle_fb_info_msg(ump, msg);
  874. break;
  875. case UMP_STREAM_MSG_STATUS_FB_NAME:
  876. ret = ump_handle_fb_name_msg(ump, msg);
  877. break;
  878. default:
  879. return;
  880. }
  881. /* when the message has been processed fully, wake up */
  882. if (ret > 0 && ump->stream_wait_for == status) {
  883. WRITE_ONCE(ump->stream_finished, 1);
  884. wake_up(&ump->stream_wait);
  885. }
  886. }
  887. /**
  888. * snd_ump_parse_endpoint - parse endpoint and create function blocks
  889. * @ump: UMP object
  890. *
  891. * Returns 0 for successful parse, -ENODEV if device doesn't respond
  892. * (or the query is unsupported), or other error code for serious errors.
  893. */
  894. int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump)
  895. {
  896. int blk, err;
  897. u32 msg;
  898. if (!(ump->core.info_flags & SNDRV_RAWMIDI_INFO_DUPLEX))
  899. return -ENODEV;
  900. err = ump_request_open(ump);
  901. if (err < 0) {
  902. ump_dbg(ump, "Unable to open rawmidi device: %d\n", err);
  903. return err;
  904. }
  905. /* Check Endpoint Information */
  906. msg = ump_stream_compose(UMP_STREAM_MSG_STATUS_EP_DISCOVERY, 0) |
  907. 0x0101; /* UMP version 1.1 */
  908. err = ump_req_msg(ump, msg, UMP_STREAM_MSG_REQUEST_EP_INFO,
  909. UMP_STREAM_MSG_STATUS_EP_INFO);
  910. if (err < 0) {
  911. ump_dbg(ump, "Unable to get UMP EP info\n");
  912. goto error;
  913. }
  914. /* Request Endpoint Device Info */
  915. err = ump_req_msg(ump, msg, UMP_STREAM_MSG_REQUEST_DEVICE_INFO,
  916. UMP_STREAM_MSG_STATUS_DEVICE_INFO);
  917. if (err < 0)
  918. ump_dbg(ump, "Unable to get UMP EP device info\n");
  919. /* Request Endpoint Name */
  920. err = ump_req_msg(ump, msg, UMP_STREAM_MSG_REQUEST_EP_NAME,
  921. UMP_STREAM_MSG_STATUS_EP_NAME);
  922. if (err < 0)
  923. ump_dbg(ump, "Unable to get UMP EP name string\n");
  924. /* Request Endpoint Product ID */
  925. err = ump_req_msg(ump, msg, UMP_STREAM_MSG_REQUEST_PRODUCT_ID,
  926. UMP_STREAM_MSG_STATUS_PRODUCT_ID);
  927. if (err < 0)
  928. ump_dbg(ump, "Unable to get UMP EP product ID string\n");
  929. /* Get the current stream configuration */
  930. err = ump_req_msg(ump, msg, UMP_STREAM_MSG_REQUEST_STREAM_CFG,
  931. UMP_STREAM_MSG_STATUS_STREAM_CFG);
  932. if (err < 0)
  933. ump_dbg(ump, "Unable to get UMP EP stream config\n");
  934. /* If no protocol is set by some reason, assume the valid one */
  935. choose_default_protocol(ump);
  936. /* Query and create blocks from Function Blocks */
  937. for (blk = 0; blk < ump->info.num_blocks; blk++) {
  938. err = create_block_from_fb_info(ump, blk);
  939. if (err < 0)
  940. continue;
  941. }
  942. /* initialize group attributions */
  943. snd_ump_update_group_attrs(ump);
  944. error:
  945. ump->parsed = true;
  946. ump_request_close(ump);
  947. if (err == -ETIMEDOUT)
  948. err = -ENODEV;
  949. return err;
  950. }
  951. EXPORT_SYMBOL_GPL(snd_ump_parse_endpoint);
  952. #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
  953. /*
  954. * Legacy rawmidi support
  955. */
  956. static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
  957. {
  958. struct snd_ump_endpoint *ump = substream->rmidi->private_data;
  959. int dir = substream->stream;
  960. int group = ump->legacy_mapping[substream->number];
  961. int err;
  962. guard(mutex)(&ump->open_mutex);
  963. if (ump->legacy_substreams[dir][group])
  964. return -EBUSY;
  965. if (!ump->groups[group].active)
  966. return -ENODEV;
  967. if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
  968. if (!ump->legacy_out_opens) {
  969. err = snd_rawmidi_kernel_open(&ump->core, 0,
  970. SNDRV_RAWMIDI_LFLG_OUTPUT |
  971. SNDRV_RAWMIDI_LFLG_APPEND,
  972. &ump->legacy_out_rfile);
  973. if (err < 0)
  974. return err;
  975. }
  976. ump->legacy_out_opens++;
  977. snd_ump_convert_reset(&ump->out_cvts[group]);
  978. }
  979. guard(spinlock_irq)(&ump->legacy_locks[dir]);
  980. ump->legacy_substreams[dir][group] = substream;
  981. return 0;
  982. }
  983. static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
  984. {
  985. struct snd_ump_endpoint *ump = substream->rmidi->private_data;
  986. int dir = substream->stream;
  987. int group = ump->legacy_mapping[substream->number];
  988. guard(mutex)(&ump->open_mutex);
  989. scoped_guard(spinlock_irq, &ump->legacy_locks[dir])
  990. ump->legacy_substreams[dir][group] = NULL;
  991. if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
  992. if (!--ump->legacy_out_opens)
  993. snd_rawmidi_kernel_release(&ump->legacy_out_rfile);
  994. }
  995. return 0;
  996. }
  997. static void snd_ump_legacy_trigger(struct snd_rawmidi_substream *substream,
  998. int up)
  999. {
  1000. struct snd_ump_endpoint *ump = substream->rmidi->private_data;
  1001. int dir = substream->stream;
  1002. ump->ops->trigger(ump, dir, up);
  1003. }
  1004. static void snd_ump_legacy_drain(struct snd_rawmidi_substream *substream)
  1005. {
  1006. struct snd_ump_endpoint *ump = substream->rmidi->private_data;
  1007. if (ump->ops->drain)
  1008. ump->ops->drain(ump, SNDRV_RAWMIDI_STREAM_OUTPUT);
  1009. }
  1010. static int snd_ump_legacy_dev_register(struct snd_rawmidi *rmidi)
  1011. {
  1012. /* dummy, just for avoiding create superfluous seq clients */
  1013. return 0;
  1014. }
  1015. static const struct snd_rawmidi_ops snd_ump_legacy_input_ops = {
  1016. .open = snd_ump_legacy_open,
  1017. .close = snd_ump_legacy_close,
  1018. .trigger = snd_ump_legacy_trigger,
  1019. };
  1020. static const struct snd_rawmidi_ops snd_ump_legacy_output_ops = {
  1021. .open = snd_ump_legacy_open,
  1022. .close = snd_ump_legacy_close,
  1023. .trigger = snd_ump_legacy_trigger,
  1024. .drain = snd_ump_legacy_drain,
  1025. };
  1026. static const struct snd_rawmidi_global_ops snd_ump_legacy_ops = {
  1027. .dev_register = snd_ump_legacy_dev_register,
  1028. };
  1029. static int process_legacy_output(struct snd_ump_endpoint *ump,
  1030. u32 *buffer, int count)
  1031. {
  1032. struct snd_rawmidi_substream *substream;
  1033. struct ump_cvt_to_ump *ctx;
  1034. const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT;
  1035. unsigned int protocol;
  1036. unsigned char c;
  1037. int group, size = 0;
  1038. if (!ump->out_cvts || !ump->legacy_out_opens)
  1039. return 0;
  1040. guard(spinlock_irqsave)(&ump->legacy_locks[dir]);
  1041. for (group = 0; group < SNDRV_UMP_MAX_GROUPS; group++) {
  1042. substream = ump->legacy_substreams[dir][group];
  1043. if (!substream)
  1044. continue;
  1045. ctx = &ump->out_cvts[group];
  1046. protocol = ump->info.protocol;
  1047. if ((protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) &&
  1048. ump->groups[group].is_midi1)
  1049. protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1;
  1050. while (!ctx->ump_bytes &&
  1051. snd_rawmidi_transmit(substream, &c, 1) > 0)
  1052. snd_ump_convert_to_ump(ctx, group, protocol, c);
  1053. if (ctx->ump_bytes && ctx->ump_bytes <= count) {
  1054. size = ctx->ump_bytes;
  1055. memcpy(buffer, ctx->ump, size);
  1056. ctx->ump_bytes = 0;
  1057. break;
  1058. }
  1059. }
  1060. return size;
  1061. }
  1062. static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
  1063. int words)
  1064. {
  1065. struct snd_rawmidi_substream *substream;
  1066. unsigned char buf[16];
  1067. unsigned char group;
  1068. const int dir = SNDRV_RAWMIDI_STREAM_INPUT;
  1069. int size;
  1070. size = snd_ump_convert_from_ump(src, buf, &group);
  1071. if (size <= 0)
  1072. return;
  1073. guard(spinlock_irqsave)(&ump->legacy_locks[dir]);
  1074. substream = ump->legacy_substreams[dir][group];
  1075. if (substream)
  1076. snd_rawmidi_receive(substream, buf, size);
  1077. }
  1078. /* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */
  1079. static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
  1080. {
  1081. struct snd_ump_block *fb;
  1082. unsigned int group_maps = 0;
  1083. int i, num;
  1084. if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) {
  1085. list_for_each_entry(fb, &ump->block_list, list) {
  1086. for (i = 0; i < fb->info.num_groups; i++)
  1087. group_maps |= 1U << (fb->info.first_group + i);
  1088. }
  1089. if (!group_maps)
  1090. ump_info(ump, "No UMP Group is found in FB\n");
  1091. }
  1092. /* use all groups for non-static case */
  1093. if (!group_maps)
  1094. group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1;
  1095. num = 0;
  1096. for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
  1097. if (group_maps & (1U << i))
  1098. ump->legacy_mapping[num++] = i;
  1099. return num;
  1100. }
  1101. static void fill_substream_names(struct snd_ump_endpoint *ump,
  1102. struct snd_rawmidi *rmidi, int dir)
  1103. {
  1104. struct snd_rawmidi_substream *s;
  1105. const char *name;
  1106. int idx;
  1107. list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
  1108. idx = ump->legacy_mapping[s->number];
  1109. name = ump->groups[idx].name;
  1110. if (!*name)
  1111. name = ump->info.name;
  1112. scnprintf(s->name, sizeof(s->name), "Group %d (%.16s)%s",
  1113. idx + 1, name,
  1114. ump->groups[idx].active ? "" : " [Inactive]");
  1115. }
  1116. }
  1117. static void update_legacy_names(struct snd_ump_endpoint *ump)
  1118. {
  1119. struct snd_rawmidi *rmidi = ump->legacy_rmidi;
  1120. fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
  1121. fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
  1122. }
  1123. int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
  1124. char *id, int device)
  1125. {
  1126. struct snd_rawmidi *rmidi;
  1127. bool input, output;
  1128. int err, num;
  1129. ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS,
  1130. sizeof(*ump->out_cvts), GFP_KERNEL);
  1131. if (!ump->out_cvts)
  1132. return -ENOMEM;
  1133. num = fill_legacy_mapping(ump);
  1134. input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT;
  1135. output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT;
  1136. err = snd_rawmidi_new(ump->core.card, id, device,
  1137. output ? num : 0, input ? num : 0,
  1138. &rmidi);
  1139. if (err < 0) {
  1140. kfree(ump->out_cvts);
  1141. return err;
  1142. }
  1143. if (input)
  1144. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  1145. &snd_ump_legacy_input_ops);
  1146. if (output)
  1147. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  1148. &snd_ump_legacy_output_ops);
  1149. snprintf(rmidi->name, sizeof(rmidi->name), "%.68s (MIDI 1.0)",
  1150. ump->info.name);
  1151. rmidi->info_flags = ump->core.info_flags & ~SNDRV_RAWMIDI_INFO_UMP;
  1152. rmidi->ops = &snd_ump_legacy_ops;
  1153. rmidi->private_data = ump;
  1154. ump->legacy_rmidi = rmidi;
  1155. update_legacy_names(ump);
  1156. ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id);
  1157. return 0;
  1158. }
  1159. EXPORT_SYMBOL_GPL(snd_ump_attach_legacy_rawmidi);
  1160. #endif /* CONFIG_SND_UMP_LEGACY_RAWMIDI */
  1161. MODULE_DESCRIPTION("Universal MIDI Packet (UMP) Core Driver");
  1162. MODULE_LICENSE("GPL");