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