ALSA: seq: ump: Fix conversion from MIDI2 to MIDI1 UMP messages
[linux-2.6-block.git] / sound / core / seq / seq_ump_convert.c
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 }