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