1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ALSA sequencer event conversion between UMP and legacy clients 4 */ 5 6 #include <linux/init.h> 7 #include <linux/errno.h> 8 #include <linux/string.h> 9 #include <sound/core.h> 10 #include <sound/ump.h> 11 #include <sound/ump_msg.h> 12 #include "seq_ump_convert.h" 13 14 /* 15 * Upgrade / downgrade value bits 16 */ 17 static u8 downscale_32_to_7bit(u32 src) 18 { 19 return src >> 25; 20 } 21 22 static u16 downscale_32_to_14bit(u32 src) 23 { 24 return src >> 18; 25 } 26 27 static u8 downscale_16_to_7bit(u16 src) 28 { 29 return src >> 9; 30 } 31 32 static u16 upscale_7_to_16bit(u8 src) 33 { 34 u16 val, repeat; 35 36 val = (u16)src << 9; 37 if (src <= 0x40) 38 return val; 39 repeat = src & 0x3f; 40 return val | (repeat << 3) | (repeat >> 3); 41 } 42 43 static u32 upscale_7_to_32bit(u8 src) 44 { 45 u32 val, repeat; 46 47 val = src << 25; 48 if (src <= 0x40) 49 return val; 50 repeat = src & 0x3f; 51 return val | (repeat << 19) | (repeat << 13) | 52 (repeat << 7) | (repeat << 1) | (repeat >> 5); 53 } 54 55 static u32 upscale_14_to_32bit(u16 src) 56 { 57 u32 val, repeat; 58 59 val = src << 18; 60 if (src <= 0x2000) 61 return val; 62 repeat = src & 0x1fff; 63 return val | (repeat << 5) | (repeat >> 8); 64 } 65 66 static unsigned char get_ump_group(struct snd_seq_client_port *port) 67 { 68 return port->ump_group ? (port->ump_group - 1) : 0; 69 } 70 71 /* create a UMP header */ 72 #define make_raw_ump(port, type) \ 73 ump_compose(type, get_ump_group(port), 0, 0) 74 75 /* 76 * UMP -> MIDI1 sequencer event 77 */ 78 79 /* MIDI 1.0 CVM */ 80 81 /* encode note event */ 82 static void ump_midi1_to_note_ev(const union snd_ump_midi1_msg *val, 83 struct snd_seq_event *ev) 84 { 85 ev->data.note.channel = val->note.channel; 86 ev->data.note.note = val->note.note; 87 ev->data.note.velocity = val->note.velocity; 88 } 89 90 /* encode one parameter controls */ 91 static void ump_midi1_to_ctrl_ev(const union snd_ump_midi1_msg *val, 92 struct snd_seq_event *ev) 93 { 94 ev->data.control.channel = val->caf.channel; 95 ev->data.control.value = val->caf.data; 96 } 97 98 /* encode pitch wheel change */ 99 static void ump_midi1_to_pitchbend_ev(const union snd_ump_midi1_msg *val, 100 struct snd_seq_event *ev) 101 { 102 ev->data.control.channel = val->pb.channel; 103 ev->data.control.value = (val->pb.data_msb << 7) | val->pb.data_lsb; 104 ev->data.control.value -= 8192; 105 } 106 107 /* encode midi control change */ 108 static void ump_midi1_to_cc_ev(const union snd_ump_midi1_msg *val, 109 struct snd_seq_event *ev) 110 { 111 ev->data.control.channel = val->cc.channel; 112 ev->data.control.param = val->cc.index; 113 ev->data.control.value = val->cc.data; 114 } 115 116 /* Encoding MIDI 1.0 UMP packet */ 117 struct seq_ump_midi1_to_ev { 118 int seq_type; 119 void (*encode)(const union snd_ump_midi1_msg *val, struct snd_seq_event *ev); 120 }; 121 122 /* Encoders for MIDI1 status 0x80-0xe0 */ 123 static struct seq_ump_midi1_to_ev midi1_msg_encoders[] = { 124 {SNDRV_SEQ_EVENT_NOTEOFF, ump_midi1_to_note_ev}, /* 0x80 */ 125 {SNDRV_SEQ_EVENT_NOTEON, ump_midi1_to_note_ev}, /* 0x90 */ 126 {SNDRV_SEQ_EVENT_KEYPRESS, ump_midi1_to_note_ev}, /* 0xa0 */ 127 {SNDRV_SEQ_EVENT_CONTROLLER, ump_midi1_to_cc_ev}, /* 0xb0 */ 128 {SNDRV_SEQ_EVENT_PGMCHANGE, ump_midi1_to_ctrl_ev}, /* 0xc0 */ 129 {SNDRV_SEQ_EVENT_CHANPRESS, ump_midi1_to_ctrl_ev}, /* 0xd0 */ 130 {SNDRV_SEQ_EVENT_PITCHBEND, ump_midi1_to_pitchbend_ev}, /* 0xe0 */ 131 }; 132 133 static int cvt_ump_midi1_to_event(const union snd_ump_midi1_msg *val, 134 struct snd_seq_event *ev) 135 { 136 unsigned char status = val->note.status; 137 138 if (status < 0x8 || status > 0xe) 139 return 0; /* invalid - skip */ 140 status -= 8; 141 ev->type = midi1_msg_encoders[status].seq_type; 142 ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; 143 midi1_msg_encoders[status].encode(val, ev); 144 return 1; 145 } 146 147 /* MIDI System message */ 148 149 /* encode one parameter value*/ 150 static void ump_system_to_one_param_ev(const union snd_ump_midi1_msg *val, 151 struct snd_seq_event *ev) 152 { 153 ev->data.control.value = val->system.parm1; 154 } 155 156 /* encode song position */ 157 static void ump_system_to_songpos_ev(const union snd_ump_midi1_msg *val, 158 struct snd_seq_event *ev) 159 { 160 ev->data.control.value = (val->system.parm2 << 7) | val->system.parm1; 161 } 162 163 /* Encoders for 0xf0 - 0xff */ 164 static struct seq_ump_midi1_to_ev system_msg_encoders[] = { 165 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf0 */ 166 {SNDRV_SEQ_EVENT_QFRAME, ump_system_to_one_param_ev}, /* 0xf1 */ 167 {SNDRV_SEQ_EVENT_SONGPOS, ump_system_to_songpos_ev}, /* 0xf2 */ 168 {SNDRV_SEQ_EVENT_SONGSEL, ump_system_to_one_param_ev}, /* 0xf3 */ 169 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf4 */ 170 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf5 */ 171 {SNDRV_SEQ_EVENT_TUNE_REQUEST, NULL}, /* 0xf6 */ 172 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf7 */ 173 {SNDRV_SEQ_EVENT_CLOCK, NULL}, /* 0xf8 */ 174 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf9 */ 175 {SNDRV_SEQ_EVENT_START, NULL}, /* 0xfa */ 176 {SNDRV_SEQ_EVENT_CONTINUE, NULL}, /* 0xfb */ 177 {SNDRV_SEQ_EVENT_STOP, NULL}, /* 0xfc */ 178 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xfd */ 179 {SNDRV_SEQ_EVENT_SENSING, NULL}, /* 0xfe */ 180 {SNDRV_SEQ_EVENT_RESET, NULL}, /* 0xff */ 181 }; 182 183 static int cvt_ump_system_to_event(const union snd_ump_midi1_msg *val, 184 struct snd_seq_event *ev) 185 { 186 unsigned char status = val->system.status; 187 188 if ((status & 0xf0) != UMP_MIDI1_MSG_REALTIME) 189 return 0; /* invalid status - skip */ 190 status &= 0x0f; 191 ev->type = system_msg_encoders[status].seq_type; 192 ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; 193 if (ev->type == SNDRV_SEQ_EVENT_NONE) 194 return 0; 195 if (system_msg_encoders[status].encode) 196 system_msg_encoders[status].encode(val, ev); 197 return 1; 198 } 199 200 /* MIDI 2.0 CVM */ 201 202 /* encode note event */ 203 static int ump_midi2_to_note_ev(const union snd_ump_midi2_msg *val, 204 struct snd_seq_event *ev) 205 { 206 ev->data.note.channel = val->note.channel; 207 ev->data.note.note = val->note.note; 208 ev->data.note.velocity = downscale_16_to_7bit(val->note.velocity); 209 /* correct note-on velocity 0 to 1; 210 * it's no longer equivalent as not-off for MIDI 2.0 211 */ 212 if (ev->type == SNDRV_SEQ_EVENT_NOTEON && 213 !ev->data.note.velocity) 214 ev->data.note.velocity = 1; 215 return 1; 216 } 217 218 /* encode pitch wheel change */ 219 static int ump_midi2_to_pitchbend_ev(const union snd_ump_midi2_msg *val, 220 struct snd_seq_event *ev) 221 { 222 ev->data.control.channel = val->pb.channel; 223 ev->data.control.value = downscale_32_to_14bit(val->pb.data); 224 ev->data.control.value -= 8192; 225 return 1; 226 } 227 228 /* encode midi control change */ 229 static int ump_midi2_to_cc_ev(const union snd_ump_midi2_msg *val, 230 struct snd_seq_event *ev) 231 { 232 ev->data.control.channel = val->cc.channel; 233 ev->data.control.param = val->cc.index; 234 ev->data.control.value = downscale_32_to_7bit(val->cc.data); 235 return 1; 236 } 237 238 /* encode midi program change */ 239 static int ump_midi2_to_pgm_ev(const union snd_ump_midi2_msg *val, 240 struct snd_seq_event *ev) 241 { 242 int size = 1; 243 244 ev->data.control.channel = val->pg.channel; 245 if (val->pg.bank_valid) { 246 ev->type = SNDRV_SEQ_EVENT_CONTROL14; 247 ev->data.control.param = UMP_CC_BANK_SELECT; 248 ev->data.control.value = (val->pg.bank_msb << 7) | val->pg.bank_lsb; 249 ev[1] = ev[0]; 250 ev++; 251 ev->type = SNDRV_SEQ_EVENT_PGMCHANGE; 252 size = 2; 253 } 254 ev->data.control.value = val->pg.program; 255 return size; 256 } 257 258 /* encode one parameter controls */ 259 static int ump_midi2_to_ctrl_ev(const union snd_ump_midi2_msg *val, 260 struct snd_seq_event *ev) 261 { 262 ev->data.control.channel = val->caf.channel; 263 ev->data.control.value = downscale_32_to_7bit(val->caf.data); 264 return 1; 265 } 266 267 /* encode RPN/NRPN */ 268 static int ump_midi2_to_rpn_ev(const union snd_ump_midi2_msg *val, 269 struct snd_seq_event *ev) 270 { 271 ev->data.control.channel = val->rpn.channel; 272 ev->data.control.param = (val->rpn.bank << 7) | val->rpn.index; 273 ev->data.control.value = downscale_32_to_14bit(val->rpn.data); 274 return 1; 275 } 276 277 /* Encoding MIDI 2.0 UMP Packet */ 278 struct seq_ump_midi2_to_ev { 279 int seq_type; 280 int (*encode)(const union snd_ump_midi2_msg *val, struct snd_seq_event *ev); 281 }; 282 283 /* Encoders for MIDI2 status 0x00-0xf0 */ 284 static struct seq_ump_midi2_to_ev midi2_msg_encoders[] = { 285 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x00 */ 286 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x10 */ 287 {SNDRV_SEQ_EVENT_REGPARAM, ump_midi2_to_rpn_ev}, /* 0x20 */ 288 {SNDRV_SEQ_EVENT_NONREGPARAM, ump_midi2_to_rpn_ev}, /* 0x30 */ 289 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x40 */ 290 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x50 */ 291 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x60 */ 292 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0x70 */ 293 {SNDRV_SEQ_EVENT_NOTEOFF, ump_midi2_to_note_ev}, /* 0x80 */ 294 {SNDRV_SEQ_EVENT_NOTEON, ump_midi2_to_note_ev}, /* 0x90 */ 295 {SNDRV_SEQ_EVENT_KEYPRESS, ump_midi2_to_note_ev}, /* 0xa0 */ 296 {SNDRV_SEQ_EVENT_CONTROLLER, ump_midi2_to_cc_ev}, /* 0xb0 */ 297 {SNDRV_SEQ_EVENT_PGMCHANGE, ump_midi2_to_pgm_ev}, /* 0xc0 */ 298 {SNDRV_SEQ_EVENT_CHANPRESS, ump_midi2_to_ctrl_ev}, /* 0xd0 */ 299 {SNDRV_SEQ_EVENT_PITCHBEND, ump_midi2_to_pitchbend_ev}, /* 0xe0 */ 300 {SNDRV_SEQ_EVENT_NONE, NULL}, /* 0xf0 */ 301 }; 302 303 static int cvt_ump_midi2_to_event(const union snd_ump_midi2_msg *val, 304 struct snd_seq_event *ev) 305 { 306 unsigned char status = val->note.status; 307 308 ev->type = midi2_msg_encoders[status].seq_type; 309 if (ev->type == SNDRV_SEQ_EVENT_NONE) 310 return 0; /* skip */ 311 ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; 312 return midi2_msg_encoders[status].encode(val, ev); 313 } 314 315 /* parse and compose for a sysex var-length event */ 316 static int cvt_ump_sysex7_to_event(const u32 *data, unsigned char *buf, 317 struct snd_seq_event *ev) 318 { 319 unsigned char status; 320 unsigned char bytes; 321 u32 val; 322 int size = 0; 323 324 val = data[0]; 325 status = ump_sysex_message_status(val); 326 bytes = ump_sysex_message_length(val); 327 if (bytes > 6) 328 return 0; // skip 329 330 if (status == UMP_SYSEX_STATUS_SINGLE || 331 status == UMP_SYSEX_STATUS_START) { 332 buf[0] = UMP_MIDI1_MSG_SYSEX_START; 333 size = 1; 334 } 335 336 if (bytes > 0) 337 buf[size++] = (val >> 8) & 0x7f; 338 if (bytes > 1) 339 buf[size++] = val & 0x7f; 340 val = data[1]; 341 if (bytes > 2) 342 buf[size++] = (val >> 24) & 0x7f; 343 if (bytes > 3) 344 buf[size++] = (val >> 16) & 0x7f; 345 if (bytes > 4) 346 buf[size++] = (val >> 8) & 0x7f; 347 if (bytes > 5) 348 buf[size++] = val & 0x7f; 349 350 if (status == UMP_SYSEX_STATUS_SINGLE || 351 status == UMP_SYSEX_STATUS_END) 352 buf[size++] = UMP_MIDI1_MSG_SYSEX_END; 353 354 ev->type = SNDRV_SEQ_EVENT_SYSEX; 355 ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE; 356 ev->data.ext.len = size; 357 ev->data.ext.ptr = buf; 358 return 1; 359 } 360 361 /* convert UMP packet from MIDI 1.0 to MIDI 2.0 and deliver it */ 362 static int cvt_ump_midi1_to_midi2(struct snd_seq_client *dest, 363 struct snd_seq_client_port *dest_port, 364 struct snd_seq_event *__event, 365 int atomic, int hop) 366 { 367 struct snd_seq_ump_event *event = (struct snd_seq_ump_event *)__event; 368 struct snd_seq_ump_event ev_cvt; 369 const union snd_ump_midi1_msg *midi1 = (const union snd_ump_midi1_msg *)event->ump; 370 union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)ev_cvt.ump; 371 struct ump_cvt_to_ump_bank *cc; 372 373 ev_cvt = *event; 374 memset(&ev_cvt.ump, 0, sizeof(ev_cvt.ump)); 375 376 midi2->note.type = UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE; 377 midi2->note.group = midi1->note.group; 378 midi2->note.status = midi1->note.status; 379 midi2->note.channel = midi1->note.channel; 380 switch (midi1->note.status) { 381 case UMP_MSG_STATUS_NOTE_ON: 382 case UMP_MSG_STATUS_NOTE_OFF: 383 midi2->note.note = midi1->note.note; 384 midi2->note.velocity = upscale_7_to_16bit(midi1->note.velocity); 385 break; 386 case UMP_MSG_STATUS_POLY_PRESSURE: 387 midi2->paf.note = midi1->paf.note; 388 midi2->paf.data = upscale_7_to_32bit(midi1->paf.data); 389 break; 390 case UMP_MSG_STATUS_CC: 391 cc = &dest_port->midi2_bank[midi1->note.channel]; 392 switch (midi1->cc.index) { 393 case UMP_CC_BANK_SELECT: 394 cc->bank_set = 1; 395 cc->cc_bank_msb = midi1->cc.data; 396 return 0; // skip 397 case UMP_CC_BANK_SELECT_LSB: 398 cc->bank_set = 1; 399 cc->cc_bank_lsb = midi1->cc.data; 400 return 0; // skip 401 } 402 midi2->cc.index = midi1->cc.index; 403 midi2->cc.data = upscale_7_to_32bit(midi1->cc.data); 404 break; 405 case UMP_MSG_STATUS_PROGRAM: 406 midi2->pg.program = midi1->pg.program; 407 cc = &dest_port->midi2_bank[midi1->note.channel]; 408 if (cc->bank_set) { 409 midi2->pg.bank_valid = 1; 410 midi2->pg.bank_msb = cc->cc_bank_msb; 411 midi2->pg.bank_lsb = cc->cc_bank_lsb; 412 cc->bank_set = 0; 413 } 414 break; 415 case UMP_MSG_STATUS_CHANNEL_PRESSURE: 416 midi2->caf.data = upscale_7_to_32bit(midi1->caf.data); 417 break; 418 case UMP_MSG_STATUS_PITCH_BEND: 419 midi2->pb.data = upscale_14_to_32bit((midi1->pb.data_msb << 7) | 420 midi1->pb.data_lsb); 421 break; 422 default: 423 return 0; 424 } 425 426 return __snd_seq_deliver_single_event(dest, dest_port, 427 (struct snd_seq_event *)&ev_cvt, 428 atomic, hop); 429 } 430 431 /* convert UMP packet from MIDI 2.0 to MIDI 1.0 and deliver it */ 432 static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, 433 struct snd_seq_client_port *dest_port, 434 struct snd_seq_event *__event, 435 int atomic, int hop) 436 { 437 struct snd_seq_ump_event *event = (struct snd_seq_ump_event *)__event; 438 struct snd_seq_ump_event ev_cvt; 439 union snd_ump_midi1_msg *midi1 = (union snd_ump_midi1_msg *)ev_cvt.ump; 440 const union snd_ump_midi2_msg *midi2 = (const union snd_ump_midi2_msg *)event->ump; 441 int err; 442 u16 v; 443 444 ev_cvt = *event; 445 memset(&ev_cvt.ump, 0, sizeof(ev_cvt.ump)); 446 447 midi1->note.type = UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE; 448 midi1->note.group = midi2->note.group; 449 midi1->note.status = midi2->note.status; 450 midi1->note.channel = midi2->note.channel; 451 switch (midi2->note.status) { 452 case UMP_MSG_STATUS_NOTE_ON: 453 case UMP_MSG_STATUS_NOTE_OFF: 454 midi1->note.note = midi2->note.note; 455 midi1->note.velocity = downscale_16_to_7bit(midi2->note.velocity); 456 break; 457 case UMP_MSG_STATUS_POLY_PRESSURE: 458 midi1->paf.note = midi2->paf.note; 459 midi1->paf.data = downscale_32_to_7bit(midi2->paf.data); 460 break; 461 case UMP_MSG_STATUS_CC: 462 midi1->cc.index = midi2->cc.index; 463 midi1->cc.data = downscale_32_to_7bit(midi2->cc.data); 464 break; 465 case UMP_MSG_STATUS_PROGRAM: 466 if (midi2->pg.bank_valid) { 467 midi1->cc.status = UMP_MSG_STATUS_CC; 468 midi1->cc.index = UMP_CC_BANK_SELECT; 469 midi1->cc.data = midi2->pg.bank_msb; 470 err = __snd_seq_deliver_single_event(dest, dest_port, 471 (struct snd_seq_event *)&ev_cvt, 472 atomic, hop); 473 if (err < 0) 474 return err; 475 midi1->cc.index = UMP_CC_BANK_SELECT_LSB; 476 midi1->cc.data = midi2->pg.bank_lsb; 477 err = __snd_seq_deliver_single_event(dest, dest_port, 478 (struct snd_seq_event *)&ev_cvt, 479 atomic, hop); 480 if (err < 0) 481 return err; 482 midi1->note.status = midi2->note.status; 483 } 484 midi1->pg.program = midi2->pg.program; 485 break; 486 case UMP_MSG_STATUS_CHANNEL_PRESSURE: 487 midi1->caf.data = downscale_32_to_7bit(midi2->caf.data); 488 break; 489 case UMP_MSG_STATUS_PITCH_BEND: 490 v = downscale_32_to_14bit(midi2->pb.data); 491 midi1->pb.data_msb = v >> 7; 492 midi1->pb.data_lsb = v & 0x7f; 493 break; 494 default: 495 return 0; 496 } 497 498 return __snd_seq_deliver_single_event(dest, dest_port, 499 (struct snd_seq_event *)&ev_cvt, 500 atomic, hop); 501 } 502 503 /* convert UMP to a legacy ALSA seq event and deliver it */ 504 static int cvt_ump_to_any(struct snd_seq_client *dest, 505 struct snd_seq_client_port *dest_port, 506 struct snd_seq_event *event, 507 unsigned char type, 508 int atomic, int hop) 509 { 510 struct snd_seq_event ev_cvt[2]; /* up to two events */ 511 struct snd_seq_ump_event *ump_ev = (struct snd_seq_ump_event *)event; 512 /* use the second event as a temp buffer for saving stack usage */ 513 unsigned char *sysex_buf = (unsigned char *)(ev_cvt + 1); 514 unsigned char flags = event->flags & ~SNDRV_SEQ_EVENT_UMP; 515 int i, len, err; 516 517 ev_cvt[0] = ev_cvt[1] = *event; 518 ev_cvt[0].flags = flags; 519 ev_cvt[1].flags = flags; 520 switch (type) { 521 case UMP_MSG_TYPE_SYSTEM: 522 len = cvt_ump_system_to_event((union snd_ump_midi1_msg *)ump_ev->ump, 523 ev_cvt); 524 break; 525 case UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE: 526 len = cvt_ump_midi1_to_event((union snd_ump_midi1_msg *)ump_ev->ump, 527 ev_cvt); 528 break; 529 case UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE: 530 len = cvt_ump_midi2_to_event((union snd_ump_midi2_msg *)ump_ev->ump, 531 ev_cvt); 532 break; 533 case UMP_MSG_TYPE_DATA: 534 len = cvt_ump_sysex7_to_event(ump_ev->ump, sysex_buf, ev_cvt); 535 break; 536 default: 537 return 0; 538 } 539 540 for (i = 0; i < len; i++) { 541 err = __snd_seq_deliver_single_event(dest, dest_port, 542 &ev_cvt[i], atomic, hop); 543 if (err < 0) 544 return err; 545 } 546 547 return 0; 548 } 549 550 /* Replace UMP group field with the destination and deliver */ 551 static int deliver_with_group_convert(struct snd_seq_client *dest, 552 struct snd_seq_client_port *dest_port, 553 struct snd_seq_ump_event *ump_ev, 554 int atomic, int hop) 555 { 556 struct snd_seq_ump_event ev = *ump_ev; 557 558 /* rewrite the group to the destination port */ 559 ev.ump[0] &= ~(0xfU << 24); 560 /* fill with the new group; the dest_port->ump_group field is 1-based */ 561 ev.ump[0] |= ((dest_port->ump_group - 1) << 24); 562 563 return __snd_seq_deliver_single_event(dest, dest_port, 564 (struct snd_seq_event *)&ev, 565 atomic, hop); 566 } 567 568 /* apply the UMP event filter; return true to skip the event */ 569 static bool ump_event_filtered(struct snd_seq_client *dest, 570 const struct snd_seq_ump_event *ev) 571 { 572 unsigned char group; 573 574 group = ump_message_group(ev->ump[0]); 575 if (ump_is_groupless_msg(ump_message_type(ev->ump[0]))) 576 return dest->group_filter & (1U << 0); 577 /* check the bitmap for 1-based group number */ 578 return dest->group_filter & (1U << (group + 1)); 579 } 580 581 /* Convert from UMP packet and deliver */ 582 int snd_seq_deliver_from_ump(struct snd_seq_client *source, 583 struct snd_seq_client *dest, 584 struct snd_seq_client_port *dest_port, 585 struct snd_seq_event *event, 586 int atomic, int hop) 587 { 588 struct snd_seq_ump_event *ump_ev = (struct snd_seq_ump_event *)event; 589 unsigned char type; 590 591 if (snd_seq_ev_is_variable(event)) 592 return 0; // skip, no variable event for UMP, so far 593 if (ump_event_filtered(dest, ump_ev)) 594 return 0; // skip if group filter is set and matching 595 type = ump_message_type(ump_ev->ump[0]); 596 597 if (snd_seq_client_is_ump(dest)) { 598 if (snd_seq_client_is_midi2(dest) && 599 type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE) 600 return cvt_ump_midi1_to_midi2(dest, dest_port, 601 event, atomic, hop); 602 else if (!snd_seq_client_is_midi2(dest) && 603 type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE) 604 return cvt_ump_midi2_to_midi1(dest, dest_port, 605 event, atomic, hop); 606 /* non-EP port and different group is set? */ 607 if (dest_port->ump_group && 608 !ump_is_groupless_msg(type) && 609 ump_message_group(*ump_ev->ump) + 1 != dest_port->ump_group) 610 return deliver_with_group_convert(dest, dest_port, 611 ump_ev, atomic, hop); 612 /* copy as-is */ 613 return __snd_seq_deliver_single_event(dest, dest_port, 614 event, atomic, hop); 615 } 616 617 return cvt_ump_to_any(dest, dest_port, event, type, atomic, hop); 618 } 619 620 /* 621 * MIDI1 sequencer event -> UMP conversion 622 */ 623 624 /* Conversion to UMP MIDI 1.0 */ 625 626 /* convert note on/off event to MIDI 1.0 UMP */ 627 static int note_ev_to_ump_midi1(const struct snd_seq_event *event, 628 struct snd_seq_client_port *dest_port, 629 union snd_ump_midi1_msg *data, 630 unsigned char status) 631 { 632 if (!event->data.note.velocity) 633 status = UMP_MSG_STATUS_NOTE_OFF; 634 data->note.status = status; 635 data->note.channel = event->data.note.channel & 0x0f; 636 data->note.velocity = event->data.note.velocity & 0x7f; 637 data->note.note = event->data.note.note & 0x7f; 638 return 1; 639 } 640 641 /* convert CC event to MIDI 1.0 UMP */ 642 static int cc_ev_to_ump_midi1(const struct snd_seq_event *event, 643 struct snd_seq_client_port *dest_port, 644 union snd_ump_midi1_msg *data, 645 unsigned char status) 646 { 647 data->cc.status = status; 648 data->cc.channel = event->data.control.channel & 0x0f; 649 data->cc.index = event->data.control.param; 650 data->cc.data = event->data.control.value; 651 return 1; 652 } 653 654 /* convert one-parameter control event to MIDI 1.0 UMP */ 655 static int ctrl_ev_to_ump_midi1(const struct snd_seq_event *event, 656 struct snd_seq_client_port *dest_port, 657 union snd_ump_midi1_msg *data, 658 unsigned char status) 659 { 660 data->caf.status = status; 661 data->caf.channel = event->data.control.channel & 0x0f; 662 data->caf.data = event->data.control.value & 0x7f; 663 return 1; 664 } 665 666 /* convert pitchbend event to MIDI 1.0 UMP */ 667 static int pitchbend_ev_to_ump_midi1(const struct snd_seq_event *event, 668 struct snd_seq_client_port *dest_port, 669 union snd_ump_midi1_msg *data, 670 unsigned char status) 671 { 672 int val = event->data.control.value + 8192; 673 674 val = clamp(val, 0, 0x3fff); 675 data->pb.status = status; 676 data->pb.channel = event->data.control.channel & 0x0f; 677 data->pb.data_msb = (val >> 7) & 0x7f; 678 data->pb.data_lsb = val & 0x7f; 679 return 1; 680 } 681 682 /* convert 14bit control event to MIDI 1.0 UMP; split to two events */ 683 static int ctrl14_ev_to_ump_midi1(const struct snd_seq_event *event, 684 struct snd_seq_client_port *dest_port, 685 union snd_ump_midi1_msg *data, 686 unsigned char status) 687 { 688 data->cc.status = UMP_MSG_STATUS_CC; 689 data->cc.channel = event->data.control.channel & 0x0f; 690 data->cc.index = event->data.control.param & 0x7f; 691 if (event->data.control.param < 0x20) { 692 data->cc.data = (event->data.control.value >> 7) & 0x7f; 693 data[1] = data[0]; 694 data[1].cc.index = event->data.control.param | 0x20; 695 data[1].cc.data = event->data.control.value & 0x7f; 696 return 2; 697 } 698 699 data->cc.data = event->data.control.value & 0x7f; 700 return 1; 701 } 702 703 /* convert RPN/NRPN event to MIDI 1.0 UMP; split to four events */ 704 static int rpn_ev_to_ump_midi1(const struct snd_seq_event *event, 705 struct snd_seq_client_port *dest_port, 706 union snd_ump_midi1_msg *data, 707 unsigned char status) 708 { 709 bool is_rpn = (status == UMP_MSG_STATUS_RPN); 710 711 data->cc.status = UMP_MSG_STATUS_CC; 712 data->cc.channel = event->data.control.channel & 0x0f; 713 data[1] = data[2] = data[3] = data[0]; 714 715 data[0].cc.index = is_rpn ? UMP_CC_RPN_MSB : UMP_CC_NRPN_MSB; 716 data[0].cc.data = (event->data.control.param >> 7) & 0x7f; 717 data[1].cc.index = is_rpn ? UMP_CC_RPN_LSB : UMP_CC_NRPN_LSB; 718 data[1].cc.data = event->data.control.param & 0x7f; 719 data[2].cc.index = UMP_CC_DATA; 720 data[2].cc.data = (event->data.control.value >> 7) & 0x7f; 721 data[3].cc.index = UMP_CC_DATA_LSB; 722 data[3].cc.data = event->data.control.value & 0x7f; 723 return 4; 724 } 725 726 /* convert system / RT message to UMP */ 727 static int system_ev_to_ump_midi1(const struct snd_seq_event *event, 728 struct snd_seq_client_port *dest_port, 729 union snd_ump_midi1_msg *data, 730 unsigned char status) 731 { 732 data->system.type = UMP_MSG_TYPE_SYSTEM; // override 733 data->system.status = status; 734 return 1; 735 } 736 737 /* convert system / RT message with 1 parameter to UMP */ 738 static int system_1p_ev_to_ump_midi1(const struct snd_seq_event *event, 739 struct snd_seq_client_port *dest_port, 740 union snd_ump_midi1_msg *data, 741 unsigned char status) 742 { 743 data->system.type = UMP_MSG_TYPE_SYSTEM; // override 744 data->system.status = status; 745 data->system.parm1 = event->data.control.value & 0x7f; 746 return 1; 747 } 748 749 /* convert system / RT message with two parameters to UMP */ 750 static int system_2p_ev_to_ump_midi1(const struct snd_seq_event *event, 751 struct snd_seq_client_port *dest_port, 752 union snd_ump_midi1_msg *data, 753 unsigned char status) 754 { 755 data->system.type = UMP_MSG_TYPE_SYSTEM; // override 756 data->system.status = status; 757 data->system.parm1 = event->data.control.value & 0x7f; 758 data->system.parm2 = (event->data.control.value >> 7) & 0x7f; 759 return 1; 760 } 761 762 /* Conversion to UMP MIDI 2.0 */ 763 764 /* convert note on/off event to MIDI 2.0 UMP */ 765 static int note_ev_to_ump_midi2(const struct snd_seq_event *event, 766 struct snd_seq_client_port *dest_port, 767 union snd_ump_midi2_msg *data, 768 unsigned char status) 769 { 770 if (!event->data.note.velocity) 771 status = UMP_MSG_STATUS_NOTE_OFF; 772 data->note.status = status; 773 data->note.channel = event->data.note.channel & 0x0f; 774 data->note.note = event->data.note.note & 0x7f; 775 data->note.velocity = upscale_7_to_16bit(event->data.note.velocity & 0x7f); 776 return 1; 777 } 778 779 /* convert PAF event to MIDI 2.0 UMP */ 780 static int paf_ev_to_ump_midi2(const struct snd_seq_event *event, 781 struct snd_seq_client_port *dest_port, 782 union snd_ump_midi2_msg *data, 783 unsigned char status) 784 { 785 data->paf.status = status; 786 data->paf.channel = event->data.note.channel & 0x0f; 787 data->paf.note = event->data.note.note & 0x7f; 788 data->paf.data = upscale_7_to_32bit(event->data.note.velocity & 0x7f); 789 return 1; 790 } 791 792 static void reset_rpn(struct ump_cvt_to_ump_bank *cc) 793 { 794 cc->rpn_set = 0; 795 cc->nrpn_set = 0; 796 cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; 797 cc->cc_data_msb = cc->cc_data_lsb = 0; 798 cc->cc_data_msb_set = cc->cc_data_lsb_set = 0; 799 } 800 801 /* set up the MIDI2 RPN/NRPN packet data from the parsed info */ 802 static int fill_rpn(struct ump_cvt_to_ump_bank *cc, 803 union snd_ump_midi2_msg *data, 804 unsigned char channel, 805 bool flush) 806 { 807 if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set)) 808 return 0; // skip 809 /* when not flushing, wait for complete data set */ 810 if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set)) 811 return 0; // skip 812 813 if (cc->rpn_set) { 814 data->rpn.status = UMP_MSG_STATUS_RPN; 815 data->rpn.bank = cc->cc_rpn_msb; 816 data->rpn.index = cc->cc_rpn_lsb; 817 } else if (cc->nrpn_set) { 818 data->rpn.status = UMP_MSG_STATUS_NRPN; 819 data->rpn.bank = cc->cc_nrpn_msb; 820 data->rpn.index = cc->cc_nrpn_lsb; 821 } else { 822 return 0; // skip 823 } 824 825 data->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) | 826 cc->cc_data_lsb); 827 data->rpn.channel = channel; 828 829 reset_rpn(cc); 830 return 1; 831 } 832 833 /* convert CC event to MIDI 2.0 UMP */ 834 static int cc_ev_to_ump_midi2(const struct snd_seq_event *event, 835 struct snd_seq_client_port *dest_port, 836 union snd_ump_midi2_msg *data, 837 unsigned char status) 838 { 839 unsigned char channel = event->data.control.channel & 0x0f; 840 unsigned char index = event->data.control.param & 0x7f; 841 unsigned char val = event->data.control.value & 0x7f; 842 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 843 int ret; 844 845 /* process special CC's (bank/rpn/nrpn) */ 846 switch (index) { 847 case UMP_CC_RPN_MSB: 848 ret = fill_rpn(cc, data, channel, true); 849 cc->rpn_set = 1; 850 cc->cc_rpn_msb = val; 851 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 852 reset_rpn(cc); 853 return ret; 854 case UMP_CC_RPN_LSB: 855 ret = fill_rpn(cc, data, channel, true); 856 cc->rpn_set = 1; 857 cc->cc_rpn_lsb = val; 858 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 859 reset_rpn(cc); 860 return ret; 861 case UMP_CC_NRPN_MSB: 862 ret = fill_rpn(cc, data, channel, true); 863 cc->nrpn_set = 1; 864 cc->cc_nrpn_msb = val; 865 return ret; 866 case UMP_CC_NRPN_LSB: 867 ret = fill_rpn(cc, data, channel, true); 868 cc->nrpn_set = 1; 869 cc->cc_nrpn_lsb = val; 870 return ret; 871 case UMP_CC_DATA: 872 cc->cc_data_msb_set = 1; 873 cc->cc_data_msb = val; 874 return fill_rpn(cc, data, channel, false); 875 case UMP_CC_BANK_SELECT: 876 cc->bank_set = 1; 877 cc->cc_bank_msb = val; 878 return 0; // skip 879 case UMP_CC_BANK_SELECT_LSB: 880 cc->bank_set = 1; 881 cc->cc_bank_lsb = val; 882 return 0; // skip 883 case UMP_CC_DATA_LSB: 884 cc->cc_data_lsb_set = 1; 885 cc->cc_data_lsb = val; 886 return fill_rpn(cc, data, channel, false); 887 } 888 889 data->cc.status = status; 890 data->cc.channel = channel; 891 data->cc.index = index; 892 data->cc.data = upscale_7_to_32bit(event->data.control.value & 0x7f); 893 return 1; 894 } 895 896 /* convert one-parameter control event to MIDI 2.0 UMP */ 897 static int ctrl_ev_to_ump_midi2(const struct snd_seq_event *event, 898 struct snd_seq_client_port *dest_port, 899 union snd_ump_midi2_msg *data, 900 unsigned char status) 901 { 902 data->caf.status = status; 903 data->caf.channel = event->data.control.channel & 0x0f; 904 data->caf.data = upscale_7_to_32bit(event->data.control.value & 0x7f); 905 return 1; 906 } 907 908 /* convert program change event to MIDI 2.0 UMP */ 909 static int pgm_ev_to_ump_midi2(const struct snd_seq_event *event, 910 struct snd_seq_client_port *dest_port, 911 union snd_ump_midi2_msg *data, 912 unsigned char status) 913 { 914 unsigned char channel = event->data.control.channel & 0x0f; 915 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 916 917 data->pg.status = status; 918 data->pg.channel = channel; 919 data->pg.program = event->data.control.value & 0x7f; 920 if (cc->bank_set) { 921 data->pg.bank_valid = 1; 922 data->pg.bank_msb = cc->cc_bank_msb; 923 data->pg.bank_lsb = cc->cc_bank_lsb; 924 cc->bank_set = 0; 925 } 926 return 1; 927 } 928 929 /* convert pitchbend event to MIDI 2.0 UMP */ 930 static int pitchbend_ev_to_ump_midi2(const struct snd_seq_event *event, 931 struct snd_seq_client_port *dest_port, 932 union snd_ump_midi2_msg *data, 933 unsigned char status) 934 { 935 int val = event->data.control.value + 8192; 936 937 val = clamp(val, 0, 0x3fff); 938 data->pb.status = status; 939 data->pb.channel = event->data.control.channel & 0x0f; 940 data->pb.data = upscale_14_to_32bit(val); 941 return 1; 942 } 943 944 /* convert 14bit control event to MIDI 2.0 UMP; split to two events */ 945 static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event, 946 struct snd_seq_client_port *dest_port, 947 union snd_ump_midi2_msg *data, 948 unsigned char status) 949 { 950 unsigned char channel = event->data.control.channel & 0x0f; 951 unsigned char index = event->data.control.param & 0x7f; 952 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 953 unsigned char msb, lsb; 954 int ret; 955 956 msb = (event->data.control.value >> 7) & 0x7f; 957 lsb = event->data.control.value & 0x7f; 958 /* process special CC's (bank/rpn/nrpn) */ 959 switch (index) { 960 case UMP_CC_BANK_SELECT: 961 cc->cc_bank_msb = msb; 962 fallthrough; 963 case UMP_CC_BANK_SELECT_LSB: 964 cc->bank_set = 1; 965 cc->cc_bank_lsb = lsb; 966 return 0; // skip 967 case UMP_CC_RPN_MSB: 968 case UMP_CC_RPN_LSB: 969 ret = fill_rpn(cc, data, channel, true); 970 cc->cc_rpn_msb = msb; 971 cc->cc_rpn_lsb = lsb; 972 cc->rpn_set = 1; 973 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 974 reset_rpn(cc); 975 return ret; 976 case UMP_CC_NRPN_MSB: 977 case UMP_CC_NRPN_LSB: 978 ret = fill_rpn(cc, data, channel, true); 979 cc->cc_nrpn_msb = msb; 980 cc->nrpn_set = 1; 981 cc->cc_nrpn_lsb = lsb; 982 return ret; 983 case UMP_CC_DATA: 984 case UMP_CC_DATA_LSB: 985 cc->cc_data_msb_set = cc->cc_data_lsb_set = 1; 986 cc->cc_data_msb = msb; 987 cc->cc_data_lsb = lsb; 988 return fill_rpn(cc, data, channel, false); 989 } 990 991 data->cc.status = UMP_MSG_STATUS_CC; 992 data->cc.channel = channel; 993 data->cc.index = index; 994 if (event->data.control.param < 0x20) { 995 data->cc.data = upscale_7_to_32bit(msb); 996 data[1] = data[0]; 997 data[1].cc.index = event->data.control.param | 0x20; 998 data[1].cc.data = upscale_7_to_32bit(lsb); 999 return 2; 1000 } 1001 1002 data->cc.data = upscale_7_to_32bit(lsb); 1003 return 1; 1004 } 1005 1006 /* convert RPN/NRPN event to MIDI 2.0 UMP */ 1007 static int rpn_ev_to_ump_midi2(const struct snd_seq_event *event, 1008 struct snd_seq_client_port *dest_port, 1009 union snd_ump_midi2_msg *data, 1010 unsigned char status) 1011 { 1012 data->rpn.status = status; 1013 data->rpn.channel = event->data.control.channel; 1014 data->rpn.bank = (event->data.control.param >> 7) & 0x7f; 1015 data->rpn.index = event->data.control.param & 0x7f; 1016 data->rpn.data = upscale_14_to_32bit(event->data.control.value & 0x3fff); 1017 return 1; 1018 } 1019 1020 /* convert system / RT message to UMP */ 1021 static int system_ev_to_ump_midi2(const struct snd_seq_event *event, 1022 struct snd_seq_client_port *dest_port, 1023 union snd_ump_midi2_msg *data, 1024 unsigned char status) 1025 { 1026 return system_ev_to_ump_midi1(event, dest_port, 1027 (union snd_ump_midi1_msg *)data, 1028 status); 1029 } 1030 1031 /* convert system / RT message with 1 parameter to UMP */ 1032 static int system_1p_ev_to_ump_midi2(const struct snd_seq_event *event, 1033 struct snd_seq_client_port *dest_port, 1034 union snd_ump_midi2_msg *data, 1035 unsigned char status) 1036 { 1037 return system_1p_ev_to_ump_midi1(event, dest_port, 1038 (union snd_ump_midi1_msg *)data, 1039 status); 1040 } 1041 1042 /* convert system / RT message with two parameters to UMP */ 1043 static int system_2p_ev_to_ump_midi2(const struct snd_seq_event *event, 1044 struct snd_seq_client_port *dest_port, 1045 union snd_ump_midi2_msg *data, 1046 unsigned char status) 1047 { 1048 return system_2p_ev_to_ump_midi1(event, dest_port, 1049 (union snd_ump_midi1_msg *)data, 1050 status); 1051 } 1052 1053 struct seq_ev_to_ump { 1054 int seq_type; 1055 unsigned char status; 1056 int (*midi1_encode)(const struct snd_seq_event *event, 1057 struct snd_seq_client_port *dest_port, 1058 union snd_ump_midi1_msg *data, 1059 unsigned char status); 1060 int (*midi2_encode)(const struct snd_seq_event *event, 1061 struct snd_seq_client_port *dest_port, 1062 union snd_ump_midi2_msg *data, 1063 unsigned char status); 1064 }; 1065 1066 static const struct seq_ev_to_ump seq_ev_ump_encoders[] = { 1067 { SNDRV_SEQ_EVENT_NOTEON, UMP_MSG_STATUS_NOTE_ON, 1068 note_ev_to_ump_midi1, note_ev_to_ump_midi2 }, 1069 { SNDRV_SEQ_EVENT_NOTEOFF, UMP_MSG_STATUS_NOTE_OFF, 1070 note_ev_to_ump_midi1, note_ev_to_ump_midi2 }, 1071 { SNDRV_SEQ_EVENT_KEYPRESS, UMP_MSG_STATUS_POLY_PRESSURE, 1072 note_ev_to_ump_midi1, paf_ev_to_ump_midi2 }, 1073 { SNDRV_SEQ_EVENT_CONTROLLER, UMP_MSG_STATUS_CC, 1074 cc_ev_to_ump_midi1, cc_ev_to_ump_midi2 }, 1075 { SNDRV_SEQ_EVENT_PGMCHANGE, UMP_MSG_STATUS_PROGRAM, 1076 ctrl_ev_to_ump_midi1, pgm_ev_to_ump_midi2 }, 1077 { SNDRV_SEQ_EVENT_CHANPRESS, UMP_MSG_STATUS_CHANNEL_PRESSURE, 1078 ctrl_ev_to_ump_midi1, ctrl_ev_to_ump_midi2 }, 1079 { SNDRV_SEQ_EVENT_PITCHBEND, UMP_MSG_STATUS_PITCH_BEND, 1080 pitchbend_ev_to_ump_midi1, pitchbend_ev_to_ump_midi2 }, 1081 { SNDRV_SEQ_EVENT_CONTROL14, 0, 1082 ctrl14_ev_to_ump_midi1, ctrl14_ev_to_ump_midi2 }, 1083 { SNDRV_SEQ_EVENT_NONREGPARAM, UMP_MSG_STATUS_NRPN, 1084 rpn_ev_to_ump_midi1, rpn_ev_to_ump_midi2 }, 1085 { SNDRV_SEQ_EVENT_REGPARAM, UMP_MSG_STATUS_RPN, 1086 rpn_ev_to_ump_midi1, rpn_ev_to_ump_midi2 }, 1087 { SNDRV_SEQ_EVENT_QFRAME, UMP_SYSTEM_STATUS_MIDI_TIME_CODE, 1088 system_1p_ev_to_ump_midi1, system_1p_ev_to_ump_midi2 }, 1089 { SNDRV_SEQ_EVENT_SONGPOS, UMP_SYSTEM_STATUS_SONG_POSITION, 1090 system_2p_ev_to_ump_midi1, system_2p_ev_to_ump_midi2 }, 1091 { SNDRV_SEQ_EVENT_SONGSEL, UMP_SYSTEM_STATUS_SONG_SELECT, 1092 system_1p_ev_to_ump_midi1, system_1p_ev_to_ump_midi2 }, 1093 { SNDRV_SEQ_EVENT_TUNE_REQUEST, UMP_SYSTEM_STATUS_TUNE_REQUEST, 1094 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1095 { SNDRV_SEQ_EVENT_CLOCK, UMP_SYSTEM_STATUS_TIMING_CLOCK, 1096 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1097 { SNDRV_SEQ_EVENT_START, UMP_SYSTEM_STATUS_START, 1098 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1099 { SNDRV_SEQ_EVENT_CONTINUE, UMP_SYSTEM_STATUS_CONTINUE, 1100 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1101 { SNDRV_SEQ_EVENT_STOP, UMP_SYSTEM_STATUS_STOP, 1102 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1103 { SNDRV_SEQ_EVENT_SENSING, UMP_SYSTEM_STATUS_ACTIVE_SENSING, 1104 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1105 { SNDRV_SEQ_EVENT_RESET, UMP_SYSTEM_STATUS_RESET, 1106 system_ev_to_ump_midi1, system_ev_to_ump_midi2 }, 1107 }; 1108 1109 static const struct seq_ev_to_ump *find_ump_encoder(int type) 1110 { 1111 int i; 1112 1113 for (i = 0; i < ARRAY_SIZE(seq_ev_ump_encoders); i++) 1114 if (seq_ev_ump_encoders[i].seq_type == type) 1115 return &seq_ev_ump_encoders[i]; 1116 1117 return NULL; 1118 } 1119 1120 static void setup_ump_event(struct snd_seq_ump_event *dest, 1121 const struct snd_seq_event *src) 1122 { 1123 memcpy(dest, src, sizeof(*src)); 1124 dest->type = 0; 1125 dest->flags |= SNDRV_SEQ_EVENT_UMP; 1126 dest->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 1127 memset(dest->ump, 0, sizeof(dest->ump)); 1128 } 1129 1130 /* Convert ALSA seq event to UMP MIDI 1.0 and deliver it */ 1131 static int cvt_to_ump_midi1(struct snd_seq_client *dest, 1132 struct snd_seq_client_port *dest_port, 1133 struct snd_seq_event *event, 1134 int atomic, int hop) 1135 { 1136 const struct seq_ev_to_ump *encoder; 1137 struct snd_seq_ump_event ev_cvt; 1138 union snd_ump_midi1_msg data[4]; 1139 int i, n, err; 1140 1141 encoder = find_ump_encoder(event->type); 1142 if (!encoder) 1143 return __snd_seq_deliver_single_event(dest, dest_port, 1144 event, atomic, hop); 1145 1146 data->raw = make_raw_ump(dest_port, UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE); 1147 n = encoder->midi1_encode(event, dest_port, data, encoder->status); 1148 if (!n) 1149 return 0; 1150 1151 setup_ump_event(&ev_cvt, event); 1152 for (i = 0; i < n; i++) { 1153 ev_cvt.ump[0] = data[i].raw; 1154 err = __snd_seq_deliver_single_event(dest, dest_port, 1155 (struct snd_seq_event *)&ev_cvt, 1156 atomic, hop); 1157 if (err < 0) 1158 return err; 1159 } 1160 1161 return 0; 1162 } 1163 1164 /* Convert ALSA seq event to UMP MIDI 2.0 and deliver it */ 1165 static int cvt_to_ump_midi2(struct snd_seq_client *dest, 1166 struct snd_seq_client_port *dest_port, 1167 struct snd_seq_event *event, 1168 int atomic, int hop) 1169 { 1170 const struct seq_ev_to_ump *encoder; 1171 struct snd_seq_ump_event ev_cvt; 1172 union snd_ump_midi2_msg data[2]; 1173 int i, n, err; 1174 1175 encoder = find_ump_encoder(event->type); 1176 if (!encoder) 1177 return __snd_seq_deliver_single_event(dest, dest_port, 1178 event, atomic, hop); 1179 1180 data->raw[0] = make_raw_ump(dest_port, UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE); 1181 data->raw[1] = 0; 1182 n = encoder->midi2_encode(event, dest_port, data, encoder->status); 1183 if (!n) 1184 return 0; 1185 1186 setup_ump_event(&ev_cvt, event); 1187 for (i = 0; i < n; i++) { 1188 memcpy(ev_cvt.ump, &data[i], sizeof(data[i])); 1189 err = __snd_seq_deliver_single_event(dest, dest_port, 1190 (struct snd_seq_event *)&ev_cvt, 1191 atomic, hop); 1192 if (err < 0) 1193 return err; 1194 } 1195 1196 return 0; 1197 } 1198 1199 /* Fill up a sysex7 UMP from the byte stream */ 1200 static void fill_sysex7_ump(struct snd_seq_client_port *dest_port, 1201 u32 *val, u8 status, u8 *buf, int len) 1202 { 1203 memset(val, 0, 8); 1204 memcpy((u8 *)val + 2, buf, len); 1205 #ifdef __LITTLE_ENDIAN 1206 swab32_array(val, 2); 1207 #endif 1208 val[0] |= ump_compose(UMP_MSG_TYPE_DATA, get_ump_group(dest_port), 1209 status, len); 1210 } 1211 1212 /* Convert sysex var event to UMP sysex7 packets and deliver them */ 1213 static int cvt_sysex_to_ump(struct snd_seq_client *dest, 1214 struct snd_seq_client_port *dest_port, 1215 struct snd_seq_event *event, 1216 int atomic, int hop) 1217 { 1218 struct snd_seq_ump_event ev_cvt; 1219 unsigned char status; 1220 u8 buf[8], *xbuf; 1221 int offset = 0; 1222 int len, err; 1223 bool finished = false; 1224 1225 if (!snd_seq_ev_is_variable(event)) 1226 return 0; 1227 1228 setup_ump_event(&ev_cvt, event); 1229 while (!finished) { 1230 len = snd_seq_expand_var_event_at(event, sizeof(buf), buf, offset); 1231 if (len <= 0) 1232 break; 1233 if (WARN_ON(len > sizeof(buf))) 1234 break; 1235 1236 xbuf = buf; 1237 status = UMP_SYSEX_STATUS_CONTINUE; 1238 /* truncate the sysex start-marker */ 1239 if (*xbuf == UMP_MIDI1_MSG_SYSEX_START) { 1240 status = UMP_SYSEX_STATUS_START; 1241 len--; 1242 offset++; 1243 xbuf++; 1244 } 1245 1246 /* if the last of this packet or the 1st byte of the next packet 1247 * is the end-marker, finish the transfer with this packet 1248 */ 1249 if (len > 0 && len < 8 && 1250 xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1251 if (status == UMP_SYSEX_STATUS_START) 1252 status = UMP_SYSEX_STATUS_SINGLE; 1253 else 1254 status = UMP_SYSEX_STATUS_END; 1255 len--; 1256 finished = true; 1257 } 1258 1259 len = min(len, 6); 1260 fill_sysex7_ump(dest_port, ev_cvt.ump, status, xbuf, len); 1261 err = __snd_seq_deliver_single_event(dest, dest_port, 1262 (struct snd_seq_event *)&ev_cvt, 1263 atomic, hop); 1264 if (err < 0) 1265 return err; 1266 offset += len; 1267 } 1268 return 0; 1269 } 1270 1271 /* Convert to UMP packet and deliver */ 1272 int snd_seq_deliver_to_ump(struct snd_seq_client *source, 1273 struct snd_seq_client *dest, 1274 struct snd_seq_client_port *dest_port, 1275 struct snd_seq_event *event, 1276 int atomic, int hop) 1277 { 1278 if (dest->group_filter & (1U << dest_port->ump_group)) 1279 return 0; /* group filtered - skip the event */ 1280 if (event->type == SNDRV_SEQ_EVENT_SYSEX) 1281 return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop); 1282 else if (snd_seq_client_is_midi2(dest)) 1283 return cvt_to_ump_midi2(dest, dest_port, event, atomic, hop); 1284 else 1285 return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop); 1286 } 1287