xref: /openbmc/linux/sound/core/seq/seq_ump_convert.c (revision f8b39e2d)
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 		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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 
reset_rpn(struct ump_cvt_to_ump_bank * cc)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 */
fill_rpn(struct ump_cvt_to_ump_bank * cc,union snd_ump_midi2_msg * data,unsigned char channel,bool flush)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 */
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)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 
find_ump_encoder(int type)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 
setup_ump_event(struct snd_seq_ump_event * dest,const struct snd_seq_event * src)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 */
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)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 */
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)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 */
fill_sysex7_ump(struct snd_seq_client_port * dest_port,u32 * val,u8 status,u8 * buf,int len)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 */
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)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 */
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)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