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 */
downscale_32_to_7bit(u32 src)17 static u8 downscale_32_to_7bit(u32 src)
18 {
19 return src >> 25;
20 }
21
downscale_32_to_14bit(u32 src)22 static u16 downscale_32_to_14bit(u32 src)
23 {
24 return src >> 18;
25 }
26
downscale_16_to_7bit(u16 src)27 static u8 downscale_16_to_7bit(u16 src)
28 {
29 return src >> 9;
30 }
31
upscale_7_to_16bit(u8 src)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
upscale_7_to_32bit(u8 src)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
upscale_14_to_32bit(u16 src)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
get_ump_group(struct snd_seq_client_port * port)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 */
ump_midi1_to_note_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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 */
ump_midi1_to_ctrl_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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 */
ump_midi1_to_pitchbend_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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 */
ump_midi1_to_cc_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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
cvt_ump_midi1_to_event(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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*/
ump_system_to_one_param_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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 */
ump_system_to_songpos_ev(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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
cvt_ump_system_to_event(const union snd_ump_midi1_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_note_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_pitchbend_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_cc_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_pgm_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_ctrl_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
ump_midi2_to_rpn_ev(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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
cvt_ump_midi2_to_event(const union snd_ump_midi2_msg * val,struct snd_seq_event * ev)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 */
cvt_ump_sysex7_to_event(const u32 * data,unsigned char * buf,struct snd_seq_event * ev)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 */
cvt_ump_midi1_to_midi2(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * __event,int atomic,int hop)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 */
cvt_ump_midi2_to_midi1(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * __event,int atomic,int hop)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 */
cvt_ump_to_any(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,unsigned char type,int atomic,int hop)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 */
deliver_with_group_convert(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_ump_event * ump_ev,int atomic,int hop)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 */
ump_event_filtered(struct snd_seq_client * dest,const struct snd_seq_ump_event * ev)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 */
snd_seq_deliver_from_ump(struct snd_seq_client * source,struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,int atomic,int hop)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 bool is_midi2 = snd_seq_client_is_midi2(dest) &&
599 !dest_port->is_midi1;
600
601 if (is_midi2 && type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE)
602 return cvt_ump_midi1_to_midi2(dest, dest_port,
603 event, atomic, hop);
604 else if (!is_midi2 && type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE)
605 return cvt_ump_midi2_to_midi1(dest, dest_port,
606 event, atomic, hop);
607 /* non-EP port and different group is set? */
608 if (dest_port->ump_group &&
609 !ump_is_groupless_msg(type) &&
610 ump_message_group(*ump_ev->ump) + 1 != dest_port->ump_group)
611 return deliver_with_group_convert(dest, dest_port,
612 ump_ev, atomic, hop);
613 /* copy as-is */
614 return __snd_seq_deliver_single_event(dest, dest_port,
615 event, atomic, hop);
616 }
617
618 return cvt_ump_to_any(dest, dest_port, event, type, atomic, hop);
619 }
620
621 /*
622 * MIDI1 sequencer event -> UMP conversion
623 */
624
625 /* Conversion to UMP MIDI 1.0 */
626
627 /* convert note on/off event to MIDI 1.0 UMP */
note_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)628 static int note_ev_to_ump_midi1(const struct snd_seq_event *event,
629 struct snd_seq_client_port *dest_port,
630 union snd_ump_midi1_msg *data,
631 unsigned char status)
632 {
633 if (!event->data.note.velocity)
634 status = UMP_MSG_STATUS_NOTE_OFF;
635 data->note.status = status;
636 data->note.channel = event->data.note.channel & 0x0f;
637 data->note.velocity = event->data.note.velocity & 0x7f;
638 data->note.note = event->data.note.note & 0x7f;
639 return 1;
640 }
641
642 /* convert CC event to MIDI 1.0 UMP */
cc_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)643 static int cc_ev_to_ump_midi1(const struct snd_seq_event *event,
644 struct snd_seq_client_port *dest_port,
645 union snd_ump_midi1_msg *data,
646 unsigned char status)
647 {
648 data->cc.status = status;
649 data->cc.channel = event->data.control.channel & 0x0f;
650 data->cc.index = event->data.control.param;
651 data->cc.data = event->data.control.value;
652 return 1;
653 }
654
655 /* convert one-parameter control event to MIDI 1.0 UMP */
ctrl_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)656 static int ctrl_ev_to_ump_midi1(const struct snd_seq_event *event,
657 struct snd_seq_client_port *dest_port,
658 union snd_ump_midi1_msg *data,
659 unsigned char status)
660 {
661 data->caf.status = status;
662 data->caf.channel = event->data.control.channel & 0x0f;
663 data->caf.data = event->data.control.value & 0x7f;
664 return 1;
665 }
666
667 /* convert pitchbend event to MIDI 1.0 UMP */
pitchbend_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)668 static int pitchbend_ev_to_ump_midi1(const struct snd_seq_event *event,
669 struct snd_seq_client_port *dest_port,
670 union snd_ump_midi1_msg *data,
671 unsigned char status)
672 {
673 int val = event->data.control.value + 8192;
674
675 val = clamp(val, 0, 0x3fff);
676 data->pb.status = status;
677 data->pb.channel = event->data.control.channel & 0x0f;
678 data->pb.data_msb = (val >> 7) & 0x7f;
679 data->pb.data_lsb = val & 0x7f;
680 return 1;
681 }
682
683 /* convert 14bit control event to MIDI 1.0 UMP; split to two events */
ctrl14_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)684 static int ctrl14_ev_to_ump_midi1(const struct snd_seq_event *event,
685 struct snd_seq_client_port *dest_port,
686 union snd_ump_midi1_msg *data,
687 unsigned char status)
688 {
689 data->cc.status = UMP_MSG_STATUS_CC;
690 data->cc.channel = event->data.control.channel & 0x0f;
691 data->cc.index = event->data.control.param & 0x7f;
692 if (event->data.control.param < 0x20) {
693 data->cc.data = (event->data.control.value >> 7) & 0x7f;
694 data[1] = data[0];
695 data[1].cc.index = event->data.control.param | 0x20;
696 data[1].cc.data = event->data.control.value & 0x7f;
697 return 2;
698 }
699
700 data->cc.data = event->data.control.value & 0x7f;
701 return 1;
702 }
703
704 /* convert RPN/NRPN event to MIDI 1.0 UMP; split to four events */
rpn_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)705 static int rpn_ev_to_ump_midi1(const struct snd_seq_event *event,
706 struct snd_seq_client_port *dest_port,
707 union snd_ump_midi1_msg *data,
708 unsigned char status)
709 {
710 bool is_rpn = (status == UMP_MSG_STATUS_RPN);
711
712 data->cc.status = UMP_MSG_STATUS_CC;
713 data->cc.channel = event->data.control.channel & 0x0f;
714 data[1] = data[2] = data[3] = data[0];
715
716 data[0].cc.index = is_rpn ? UMP_CC_RPN_MSB : UMP_CC_NRPN_MSB;
717 data[0].cc.data = (event->data.control.param >> 7) & 0x7f;
718 data[1].cc.index = is_rpn ? UMP_CC_RPN_LSB : UMP_CC_NRPN_LSB;
719 data[1].cc.data = event->data.control.param & 0x7f;
720 data[2].cc.index = UMP_CC_DATA;
721 data[2].cc.data = (event->data.control.value >> 7) & 0x7f;
722 data[3].cc.index = UMP_CC_DATA_LSB;
723 data[3].cc.data = event->data.control.value & 0x7f;
724 return 4;
725 }
726
727 /* convert system / RT message to UMP */
system_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)728 static int system_ev_to_ump_midi1(const struct snd_seq_event *event,
729 struct snd_seq_client_port *dest_port,
730 union snd_ump_midi1_msg *data,
731 unsigned char status)
732 {
733 data->system.type = UMP_MSG_TYPE_SYSTEM; // override
734 data->system.status = status;
735 return 1;
736 }
737
738 /* convert system / RT message with 1 parameter to UMP */
system_1p_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)739 static int system_1p_ev_to_ump_midi1(const struct snd_seq_event *event,
740 struct snd_seq_client_port *dest_port,
741 union snd_ump_midi1_msg *data,
742 unsigned char status)
743 {
744 data->system.type = UMP_MSG_TYPE_SYSTEM; // override
745 data->system.status = status;
746 data->system.parm1 = event->data.control.value & 0x7f;
747 return 1;
748 }
749
750 /* convert system / RT message with two parameters to UMP */
system_2p_ev_to_ump_midi1(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi1_msg * data,unsigned char status)751 static int system_2p_ev_to_ump_midi1(const struct snd_seq_event *event,
752 struct snd_seq_client_port *dest_port,
753 union snd_ump_midi1_msg *data,
754 unsigned char status)
755 {
756 data->system.type = UMP_MSG_TYPE_SYSTEM; // override
757 data->system.status = status;
758 data->system.parm1 = event->data.control.value & 0x7f;
759 data->system.parm2 = (event->data.control.value >> 7) & 0x7f;
760 return 1;
761 }
762
763 /* Conversion to UMP MIDI 2.0 */
764
765 /* convert note on/off event to MIDI 2.0 UMP */
note_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)766 static int note_ev_to_ump_midi2(const struct snd_seq_event *event,
767 struct snd_seq_client_port *dest_port,
768 union snd_ump_midi2_msg *data,
769 unsigned char status)
770 {
771 if (!event->data.note.velocity)
772 status = UMP_MSG_STATUS_NOTE_OFF;
773 data->note.status = status;
774 data->note.channel = event->data.note.channel & 0x0f;
775 data->note.note = event->data.note.note & 0x7f;
776 data->note.velocity = upscale_7_to_16bit(event->data.note.velocity & 0x7f);
777 return 1;
778 }
779
780 /* convert PAF event to MIDI 2.0 UMP */
paf_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)781 static int paf_ev_to_ump_midi2(const struct snd_seq_event *event,
782 struct snd_seq_client_port *dest_port,
783 union snd_ump_midi2_msg *data,
784 unsigned char status)
785 {
786 data->paf.status = status;
787 data->paf.channel = event->data.note.channel & 0x0f;
788 data->paf.note = event->data.note.note & 0x7f;
789 data->paf.data = upscale_7_to_32bit(event->data.note.velocity & 0x7f);
790 return 1;
791 }
792
reset_rpn(struct ump_cvt_to_ump_bank * cc)793 static void reset_rpn(struct ump_cvt_to_ump_bank *cc)
794 {
795 cc->rpn_set = 0;
796 cc->nrpn_set = 0;
797 cc->cc_rpn_msb = cc->cc_rpn_lsb = 0;
798 cc->cc_data_msb = cc->cc_data_lsb = 0;
799 cc->cc_data_msb_set = cc->cc_data_lsb_set = 0;
800 }
801
802 /* set up the MIDI2 RPN/NRPN packet data from the parsed info */
fill_rpn(struct ump_cvt_to_ump_bank * cc,union snd_ump_midi2_msg * data,unsigned char channel,bool flush)803 static int fill_rpn(struct ump_cvt_to_ump_bank *cc,
804 union snd_ump_midi2_msg *data,
805 unsigned char channel,
806 bool flush)
807 {
808 if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set))
809 return 0; // skip
810 /* when not flushing, wait for complete data set */
811 if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set))
812 return 0; // skip
813
814 if (cc->rpn_set) {
815 data->rpn.status = UMP_MSG_STATUS_RPN;
816 data->rpn.bank = cc->cc_rpn_msb;
817 data->rpn.index = cc->cc_rpn_lsb;
818 } else if (cc->nrpn_set) {
819 data->rpn.status = UMP_MSG_STATUS_NRPN;
820 data->rpn.bank = cc->cc_nrpn_msb;
821 data->rpn.index = cc->cc_nrpn_lsb;
822 } else {
823 return 0; // skip
824 }
825
826 data->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) |
827 cc->cc_data_lsb);
828 data->rpn.channel = channel;
829
830 reset_rpn(cc);
831 return 1;
832 }
833
834 /* convert CC event to MIDI 2.0 UMP */
cc_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)835 static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
836 struct snd_seq_client_port *dest_port,
837 union snd_ump_midi2_msg *data,
838 unsigned char status)
839 {
840 unsigned char channel = event->data.control.channel & 0x0f;
841 unsigned char index = event->data.control.param & 0x7f;
842 unsigned char val = event->data.control.value & 0x7f;
843 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
844 int ret;
845
846 /* process special CC's (bank/rpn/nrpn) */
847 switch (index) {
848 case UMP_CC_RPN_MSB:
849 ret = fill_rpn(cc, data, channel, true);
850 cc->rpn_set = 1;
851 cc->cc_rpn_msb = val;
852 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f)
853 reset_rpn(cc);
854 return ret;
855 case UMP_CC_RPN_LSB:
856 ret = fill_rpn(cc, data, channel, true);
857 cc->rpn_set = 1;
858 cc->cc_rpn_lsb = val;
859 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f)
860 reset_rpn(cc);
861 return ret;
862 case UMP_CC_NRPN_MSB:
863 ret = fill_rpn(cc, data, channel, true);
864 cc->nrpn_set = 1;
865 cc->cc_nrpn_msb = val;
866 return ret;
867 case UMP_CC_NRPN_LSB:
868 ret = fill_rpn(cc, data, channel, true);
869 cc->nrpn_set = 1;
870 cc->cc_nrpn_lsb = val;
871 return ret;
872 case UMP_CC_DATA:
873 cc->cc_data_msb_set = 1;
874 cc->cc_data_msb = val;
875 return fill_rpn(cc, data, channel, false);
876 case UMP_CC_BANK_SELECT:
877 cc->bank_set = 1;
878 cc->cc_bank_msb = val;
879 return 0; // skip
880 case UMP_CC_BANK_SELECT_LSB:
881 cc->bank_set = 1;
882 cc->cc_bank_lsb = val;
883 return 0; // skip
884 case UMP_CC_DATA_LSB:
885 cc->cc_data_lsb_set = 1;
886 cc->cc_data_lsb = val;
887 return fill_rpn(cc, data, channel, false);
888 }
889
890 data->cc.status = status;
891 data->cc.channel = channel;
892 data->cc.index = index;
893 data->cc.data = upscale_7_to_32bit(event->data.control.value & 0x7f);
894 return 1;
895 }
896
897 /* convert one-parameter control event to MIDI 2.0 UMP */
ctrl_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)898 static int ctrl_ev_to_ump_midi2(const struct snd_seq_event *event,
899 struct snd_seq_client_port *dest_port,
900 union snd_ump_midi2_msg *data,
901 unsigned char status)
902 {
903 data->caf.status = status;
904 data->caf.channel = event->data.control.channel & 0x0f;
905 data->caf.data = upscale_7_to_32bit(event->data.control.value & 0x7f);
906 return 1;
907 }
908
909 /* convert program change event to MIDI 2.0 UMP */
pgm_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)910 static int pgm_ev_to_ump_midi2(const struct snd_seq_event *event,
911 struct snd_seq_client_port *dest_port,
912 union snd_ump_midi2_msg *data,
913 unsigned char status)
914 {
915 unsigned char channel = event->data.control.channel & 0x0f;
916 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
917
918 data->pg.status = status;
919 data->pg.channel = channel;
920 data->pg.program = event->data.control.value & 0x7f;
921 if (cc->bank_set) {
922 data->pg.bank_valid = 1;
923 data->pg.bank_msb = cc->cc_bank_msb;
924 data->pg.bank_lsb = cc->cc_bank_lsb;
925 cc->bank_set = 0;
926 }
927 return 1;
928 }
929
930 /* convert pitchbend event to MIDI 2.0 UMP */
pitchbend_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)931 static int pitchbend_ev_to_ump_midi2(const struct snd_seq_event *event,
932 struct snd_seq_client_port *dest_port,
933 union snd_ump_midi2_msg *data,
934 unsigned char status)
935 {
936 int val = event->data.control.value + 8192;
937
938 val = clamp(val, 0, 0x3fff);
939 data->pb.status = status;
940 data->pb.channel = event->data.control.channel & 0x0f;
941 data->pb.data = upscale_14_to_32bit(val);
942 return 1;
943 }
944
945 /* convert 14bit control event to MIDI 2.0 UMP; split to two events */
ctrl14_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)946 static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event,
947 struct snd_seq_client_port *dest_port,
948 union snd_ump_midi2_msg *data,
949 unsigned char status)
950 {
951 unsigned char channel = event->data.control.channel & 0x0f;
952 unsigned char index = event->data.control.param & 0x7f;
953 struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
954 unsigned char msb, lsb;
955 int ret;
956
957 msb = (event->data.control.value >> 7) & 0x7f;
958 lsb = event->data.control.value & 0x7f;
959 /* process special CC's (bank/rpn/nrpn) */
960 switch (index) {
961 case UMP_CC_BANK_SELECT:
962 cc->cc_bank_msb = msb;
963 fallthrough;
964 case UMP_CC_BANK_SELECT_LSB:
965 cc->bank_set = 1;
966 cc->cc_bank_lsb = lsb;
967 return 0; // skip
968 case UMP_CC_RPN_MSB:
969 case UMP_CC_RPN_LSB:
970 ret = fill_rpn(cc, data, channel, true);
971 cc->cc_rpn_msb = msb;
972 cc->cc_rpn_lsb = lsb;
973 cc->rpn_set = 1;
974 if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f)
975 reset_rpn(cc);
976 return ret;
977 case UMP_CC_NRPN_MSB:
978 case UMP_CC_NRPN_LSB:
979 ret = fill_rpn(cc, data, channel, true);
980 cc->cc_nrpn_msb = msb;
981 cc->nrpn_set = 1;
982 cc->cc_nrpn_lsb = lsb;
983 return ret;
984 case UMP_CC_DATA:
985 case UMP_CC_DATA_LSB:
986 cc->cc_data_msb_set = cc->cc_data_lsb_set = 1;
987 cc->cc_data_msb = msb;
988 cc->cc_data_lsb = lsb;
989 return fill_rpn(cc, data, channel, false);
990 }
991
992 data->cc.status = UMP_MSG_STATUS_CC;
993 data->cc.channel = channel;
994 data->cc.index = index;
995 if (event->data.control.param < 0x20) {
996 data->cc.data = upscale_7_to_32bit(msb);
997 data[1] = data[0];
998 data[1].cc.index = event->data.control.param | 0x20;
999 data[1].cc.data = upscale_7_to_32bit(lsb);
1000 return 2;
1001 }
1002
1003 data->cc.data = upscale_7_to_32bit(lsb);
1004 return 1;
1005 }
1006
1007 /* convert RPN/NRPN event to MIDI 2.0 UMP */
rpn_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)1008 static int rpn_ev_to_ump_midi2(const struct snd_seq_event *event,
1009 struct snd_seq_client_port *dest_port,
1010 union snd_ump_midi2_msg *data,
1011 unsigned char status)
1012 {
1013 data->rpn.status = status;
1014 data->rpn.channel = event->data.control.channel;
1015 data->rpn.bank = (event->data.control.param >> 7) & 0x7f;
1016 data->rpn.index = event->data.control.param & 0x7f;
1017 data->rpn.data = upscale_14_to_32bit(event->data.control.value & 0x3fff);
1018 return 1;
1019 }
1020
1021 /* convert system / RT message to UMP */
system_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)1022 static int system_ev_to_ump_midi2(const struct snd_seq_event *event,
1023 struct snd_seq_client_port *dest_port,
1024 union snd_ump_midi2_msg *data,
1025 unsigned char status)
1026 {
1027 return system_ev_to_ump_midi1(event, dest_port,
1028 (union snd_ump_midi1_msg *)data,
1029 status);
1030 }
1031
1032 /* convert system / RT message with 1 parameter to UMP */
system_1p_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)1033 static int system_1p_ev_to_ump_midi2(const struct snd_seq_event *event,
1034 struct snd_seq_client_port *dest_port,
1035 union snd_ump_midi2_msg *data,
1036 unsigned char status)
1037 {
1038 return system_1p_ev_to_ump_midi1(event, dest_port,
1039 (union snd_ump_midi1_msg *)data,
1040 status);
1041 }
1042
1043 /* convert system / RT message with two parameters to UMP */
system_2p_ev_to_ump_midi2(const struct snd_seq_event * event,struct snd_seq_client_port * dest_port,union snd_ump_midi2_msg * data,unsigned char status)1044 static int system_2p_ev_to_ump_midi2(const struct snd_seq_event *event,
1045 struct snd_seq_client_port *dest_port,
1046 union snd_ump_midi2_msg *data,
1047 unsigned char status)
1048 {
1049 return system_2p_ev_to_ump_midi1(event, dest_port,
1050 (union snd_ump_midi1_msg *)data,
1051 status);
1052 }
1053
1054 struct seq_ev_to_ump {
1055 int seq_type;
1056 unsigned char status;
1057 int (*midi1_encode)(const struct snd_seq_event *event,
1058 struct snd_seq_client_port *dest_port,
1059 union snd_ump_midi1_msg *data,
1060 unsigned char status);
1061 int (*midi2_encode)(const struct snd_seq_event *event,
1062 struct snd_seq_client_port *dest_port,
1063 union snd_ump_midi2_msg *data,
1064 unsigned char status);
1065 };
1066
1067 static const struct seq_ev_to_ump seq_ev_ump_encoders[] = {
1068 { SNDRV_SEQ_EVENT_NOTEON, UMP_MSG_STATUS_NOTE_ON,
1069 note_ev_to_ump_midi1, note_ev_to_ump_midi2 },
1070 { SNDRV_SEQ_EVENT_NOTEOFF, UMP_MSG_STATUS_NOTE_OFF,
1071 note_ev_to_ump_midi1, note_ev_to_ump_midi2 },
1072 { SNDRV_SEQ_EVENT_KEYPRESS, UMP_MSG_STATUS_POLY_PRESSURE,
1073 note_ev_to_ump_midi1, paf_ev_to_ump_midi2 },
1074 { SNDRV_SEQ_EVENT_CONTROLLER, UMP_MSG_STATUS_CC,
1075 cc_ev_to_ump_midi1, cc_ev_to_ump_midi2 },
1076 { SNDRV_SEQ_EVENT_PGMCHANGE, UMP_MSG_STATUS_PROGRAM,
1077 ctrl_ev_to_ump_midi1, pgm_ev_to_ump_midi2 },
1078 { SNDRV_SEQ_EVENT_CHANPRESS, UMP_MSG_STATUS_CHANNEL_PRESSURE,
1079 ctrl_ev_to_ump_midi1, ctrl_ev_to_ump_midi2 },
1080 { SNDRV_SEQ_EVENT_PITCHBEND, UMP_MSG_STATUS_PITCH_BEND,
1081 pitchbend_ev_to_ump_midi1, pitchbend_ev_to_ump_midi2 },
1082 { SNDRV_SEQ_EVENT_CONTROL14, 0,
1083 ctrl14_ev_to_ump_midi1, ctrl14_ev_to_ump_midi2 },
1084 { SNDRV_SEQ_EVENT_NONREGPARAM, UMP_MSG_STATUS_NRPN,
1085 rpn_ev_to_ump_midi1, rpn_ev_to_ump_midi2 },
1086 { SNDRV_SEQ_EVENT_REGPARAM, UMP_MSG_STATUS_RPN,
1087 rpn_ev_to_ump_midi1, rpn_ev_to_ump_midi2 },
1088 { SNDRV_SEQ_EVENT_QFRAME, UMP_SYSTEM_STATUS_MIDI_TIME_CODE,
1089 system_1p_ev_to_ump_midi1, system_1p_ev_to_ump_midi2 },
1090 { SNDRV_SEQ_EVENT_SONGPOS, UMP_SYSTEM_STATUS_SONG_POSITION,
1091 system_2p_ev_to_ump_midi1, system_2p_ev_to_ump_midi2 },
1092 { SNDRV_SEQ_EVENT_SONGSEL, UMP_SYSTEM_STATUS_SONG_SELECT,
1093 system_1p_ev_to_ump_midi1, system_1p_ev_to_ump_midi2 },
1094 { SNDRV_SEQ_EVENT_TUNE_REQUEST, UMP_SYSTEM_STATUS_TUNE_REQUEST,
1095 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1096 { SNDRV_SEQ_EVENT_CLOCK, UMP_SYSTEM_STATUS_TIMING_CLOCK,
1097 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1098 { SNDRV_SEQ_EVENT_START, UMP_SYSTEM_STATUS_START,
1099 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1100 { SNDRV_SEQ_EVENT_CONTINUE, UMP_SYSTEM_STATUS_CONTINUE,
1101 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1102 { SNDRV_SEQ_EVENT_STOP, UMP_SYSTEM_STATUS_STOP,
1103 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1104 { SNDRV_SEQ_EVENT_SENSING, UMP_SYSTEM_STATUS_ACTIVE_SENSING,
1105 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1106 { SNDRV_SEQ_EVENT_RESET, UMP_SYSTEM_STATUS_RESET,
1107 system_ev_to_ump_midi1, system_ev_to_ump_midi2 },
1108 };
1109
find_ump_encoder(int type)1110 static const struct seq_ev_to_ump *find_ump_encoder(int type)
1111 {
1112 int i;
1113
1114 for (i = 0; i < ARRAY_SIZE(seq_ev_ump_encoders); i++)
1115 if (seq_ev_ump_encoders[i].seq_type == type)
1116 return &seq_ev_ump_encoders[i];
1117
1118 return NULL;
1119 }
1120
setup_ump_event(struct snd_seq_ump_event * dest,const struct snd_seq_event * src)1121 static void setup_ump_event(struct snd_seq_ump_event *dest,
1122 const struct snd_seq_event *src)
1123 {
1124 memcpy(dest, src, sizeof(*src));
1125 dest->type = 0;
1126 dest->flags |= SNDRV_SEQ_EVENT_UMP;
1127 dest->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
1128 memset(dest->ump, 0, sizeof(dest->ump));
1129 }
1130
1131 /* Convert ALSA seq event to UMP MIDI 1.0 and deliver it */
cvt_to_ump_midi1(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,int atomic,int hop)1132 static int cvt_to_ump_midi1(struct snd_seq_client *dest,
1133 struct snd_seq_client_port *dest_port,
1134 struct snd_seq_event *event,
1135 int atomic, int hop)
1136 {
1137 const struct seq_ev_to_ump *encoder;
1138 struct snd_seq_ump_event ev_cvt;
1139 union snd_ump_midi1_msg data[4];
1140 int i, n, err;
1141
1142 encoder = find_ump_encoder(event->type);
1143 if (!encoder)
1144 return __snd_seq_deliver_single_event(dest, dest_port,
1145 event, atomic, hop);
1146
1147 data->raw = make_raw_ump(dest_port, UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE);
1148 n = encoder->midi1_encode(event, dest_port, data, encoder->status);
1149 if (!n)
1150 return 0;
1151
1152 setup_ump_event(&ev_cvt, event);
1153 for (i = 0; i < n; i++) {
1154 ev_cvt.ump[0] = data[i].raw;
1155 err = __snd_seq_deliver_single_event(dest, dest_port,
1156 (struct snd_seq_event *)&ev_cvt,
1157 atomic, hop);
1158 if (err < 0)
1159 return err;
1160 }
1161
1162 return 0;
1163 }
1164
1165 /* Convert ALSA seq event to UMP MIDI 2.0 and deliver it */
cvt_to_ump_midi2(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,int atomic,int hop)1166 static int cvt_to_ump_midi2(struct snd_seq_client *dest,
1167 struct snd_seq_client_port *dest_port,
1168 struct snd_seq_event *event,
1169 int atomic, int hop)
1170 {
1171 const struct seq_ev_to_ump *encoder;
1172 struct snd_seq_ump_event ev_cvt;
1173 union snd_ump_midi2_msg data[2];
1174 int i, n, err;
1175
1176 encoder = find_ump_encoder(event->type);
1177 if (!encoder)
1178 return __snd_seq_deliver_single_event(dest, dest_port,
1179 event, atomic, hop);
1180
1181 data->raw[0] = make_raw_ump(dest_port, UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE);
1182 data->raw[1] = 0;
1183 n = encoder->midi2_encode(event, dest_port, data, encoder->status);
1184 if (!n)
1185 return 0;
1186
1187 setup_ump_event(&ev_cvt, event);
1188 for (i = 0; i < n; i++) {
1189 memcpy(ev_cvt.ump, &data[i], sizeof(data[i]));
1190 err = __snd_seq_deliver_single_event(dest, dest_port,
1191 (struct snd_seq_event *)&ev_cvt,
1192 atomic, hop);
1193 if (err < 0)
1194 return err;
1195 }
1196
1197 return 0;
1198 }
1199
1200 /* Fill up a sysex7 UMP from the byte stream */
fill_sysex7_ump(struct snd_seq_client_port * dest_port,u32 * val,u8 status,u8 * buf,int len)1201 static void fill_sysex7_ump(struct snd_seq_client_port *dest_port,
1202 u32 *val, u8 status, u8 *buf, int len)
1203 {
1204 memset(val, 0, 8);
1205 memcpy((u8 *)val + 2, buf, len);
1206 #ifdef __LITTLE_ENDIAN
1207 swab32_array(val, 2);
1208 #endif
1209 val[0] |= ump_compose(UMP_MSG_TYPE_DATA, get_ump_group(dest_port),
1210 status, len);
1211 }
1212
1213 /* Convert sysex var event to UMP sysex7 packets and deliver them */
cvt_sysex_to_ump(struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,int atomic,int hop)1214 static int cvt_sysex_to_ump(struct snd_seq_client *dest,
1215 struct snd_seq_client_port *dest_port,
1216 struct snd_seq_event *event,
1217 int atomic, int hop)
1218 {
1219 struct snd_seq_ump_event ev_cvt;
1220 unsigned char status;
1221 u8 buf[8], *xbuf;
1222 int offset = 0;
1223 int len, err;
1224 bool finished = false;
1225
1226 if (!snd_seq_ev_is_variable(event))
1227 return 0;
1228
1229 setup_ump_event(&ev_cvt, event);
1230 while (!finished) {
1231 len = snd_seq_expand_var_event_at(event, sizeof(buf), buf, offset);
1232 if (len <= 0)
1233 break;
1234 if (WARN_ON(len > sizeof(buf)))
1235 break;
1236
1237 xbuf = buf;
1238 status = UMP_SYSEX_STATUS_CONTINUE;
1239 /* truncate the sysex start-marker */
1240 if (*xbuf == UMP_MIDI1_MSG_SYSEX_START) {
1241 status = UMP_SYSEX_STATUS_START;
1242 len--;
1243 offset++;
1244 xbuf++;
1245 }
1246
1247 /* if the last of this packet or the 1st byte of the next packet
1248 * is the end-marker, finish the transfer with this packet
1249 */
1250 if (len > 0 && len < 8 &&
1251 xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) {
1252 if (status == UMP_SYSEX_STATUS_START)
1253 status = UMP_SYSEX_STATUS_SINGLE;
1254 else
1255 status = UMP_SYSEX_STATUS_END;
1256 len--;
1257 finished = true;
1258 }
1259
1260 len = min(len, 6);
1261 fill_sysex7_ump(dest_port, ev_cvt.ump, status, xbuf, len);
1262 err = __snd_seq_deliver_single_event(dest, dest_port,
1263 (struct snd_seq_event *)&ev_cvt,
1264 atomic, hop);
1265 if (err < 0)
1266 return err;
1267 offset += len;
1268 }
1269 return 0;
1270 }
1271
1272 /* Convert to UMP packet and deliver */
snd_seq_deliver_to_ump(struct snd_seq_client * source,struct snd_seq_client * dest,struct snd_seq_client_port * dest_port,struct snd_seq_event * event,int atomic,int hop)1273 int snd_seq_deliver_to_ump(struct snd_seq_client *source,
1274 struct snd_seq_client *dest,
1275 struct snd_seq_client_port *dest_port,
1276 struct snd_seq_event *event,
1277 int atomic, int hop)
1278 {
1279 if (dest->group_filter & (1U << dest_port->ump_group))
1280 return 0; /* group filtered - skip the event */
1281 if (event->type == SNDRV_SEQ_EVENT_SYSEX)
1282 return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop);
1283 else if (snd_seq_client_is_midi2(dest) && !dest_port->is_midi1)
1284 return cvt_to_ump_midi2(dest, dest_port, event, atomic, hop);
1285 else
1286 return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop);
1287 }
1288