@@ -368,7 +368,7 @@ static int cvt_ump_midi1_to_midi2(struct snd_seq_client *dest,
368368 struct snd_seq_ump_event ev_cvt ;
369369 const union snd_ump_midi1_msg * midi1 = (const union snd_ump_midi1_msg * )event -> ump ;
370370 union snd_ump_midi2_msg * midi2 = (union snd_ump_midi2_msg * )ev_cvt .ump ;
371- struct snd_seq_ump_midi2_bank * cc ;
371+ struct ump_cvt_to_ump_bank * cc ;
372372
373373 ev_cvt = * event ;
374374 memset (& ev_cvt .ump , 0 , sizeof (ev_cvt .ump ));
@@ -789,28 +789,45 @@ static int paf_ev_to_ump_midi2(const struct snd_seq_event *event,
789789 return 1 ;
790790}
791791
792+ static void reset_rpn (struct ump_cvt_to_ump_bank * cc )
793+ {
794+ cc -> rpn_set = 0 ;
795+ cc -> nrpn_set = 0 ;
796+ cc -> cc_rpn_msb = cc -> cc_rpn_lsb = 0 ;
797+ cc -> cc_data_msb = cc -> cc_data_lsb = 0 ;
798+ cc -> cc_data_msb_set = cc -> cc_data_lsb_set = 0 ;
799+ }
800+
792801/* set up the MIDI2 RPN/NRPN packet data from the parsed info */
793- static void fill_rpn (struct snd_seq_ump_midi2_bank * cc ,
794- union snd_ump_midi2_msg * data ,
795- unsigned char channel )
802+ static int fill_rpn (struct ump_cvt_to_ump_bank * cc ,
803+ union snd_ump_midi2_msg * data ,
804+ unsigned char channel ,
805+ bool flush )
796806{
807+ if (!(cc -> cc_data_lsb_set || cc -> cc_data_msb_set ))
808+ return 0 ; // skip
809+ /* when not flushing, wait for complete data set */
810+ if (!flush && (!cc -> cc_data_lsb_set || !cc -> cc_data_msb_set ))
811+ return 0 ; // skip
812+
797813 if (cc -> rpn_set ) {
798814 data -> rpn .status = UMP_MSG_STATUS_RPN ;
799815 data -> rpn .bank = cc -> cc_rpn_msb ;
800816 data -> rpn .index = cc -> cc_rpn_lsb ;
801- cc -> rpn_set = 0 ;
802- cc -> cc_rpn_msb = cc -> cc_rpn_lsb = 0 ;
803- } else {
817+ } else if (cc -> nrpn_set ) {
804818 data -> rpn .status = UMP_MSG_STATUS_NRPN ;
805819 data -> rpn .bank = cc -> cc_nrpn_msb ;
806820 data -> rpn .index = cc -> cc_nrpn_lsb ;
807- cc -> nrpn_set = 0 ;
808- cc -> cc_nrpn_msb = cc -> cc_nrpn_lsb = 0 ;
821+ } else {
822+ return 0 ; // skip
809823 }
824+
810825 data -> rpn .data = upscale_14_to_32bit ((cc -> cc_data_msb << 7 ) |
811826 cc -> cc_data_lsb );
812827 data -> rpn .channel = channel ;
813- cc -> cc_data_msb = cc -> cc_data_lsb = 0 ;
828+
829+ reset_rpn (cc );
830+ return 1 ;
814831}
815832
816833/* convert CC event to MIDI 2.0 UMP */
@@ -822,29 +839,39 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
822839 unsigned char channel = event -> data .control .channel & 0x0f ;
823840 unsigned char index = event -> data .control .param & 0x7f ;
824841 unsigned char val = event -> data .control .value & 0x7f ;
825- struct snd_seq_ump_midi2_bank * cc = & dest_port -> midi2_bank [channel ];
842+ struct ump_cvt_to_ump_bank * cc = & dest_port -> midi2_bank [channel ];
843+ int ret ;
826844
827845 /* process special CC's (bank/rpn/nrpn) */
828846 switch (index ) {
829847 case UMP_CC_RPN_MSB :
848+ ret = fill_rpn (cc , data , channel , true);
830849 cc -> rpn_set = 1 ;
831850 cc -> cc_rpn_msb = val ;
832- return 0 ; // skip
851+ if (cc -> cc_rpn_msb == 0x7f && cc -> cc_rpn_lsb == 0x7f )
852+ reset_rpn (cc );
853+ return ret ;
833854 case UMP_CC_RPN_LSB :
855+ ret = fill_rpn (cc , data , channel , true);
834856 cc -> rpn_set = 1 ;
835857 cc -> cc_rpn_lsb = val ;
836- return 0 ; // skip
858+ if (cc -> cc_rpn_msb == 0x7f && cc -> cc_rpn_lsb == 0x7f )
859+ reset_rpn (cc );
860+ return ret ;
837861 case UMP_CC_NRPN_MSB :
862+ ret = fill_rpn (cc , data , channel , true);
838863 cc -> nrpn_set = 1 ;
839864 cc -> cc_nrpn_msb = val ;
840- return 0 ; // skip
865+ return ret ;
841866 case UMP_CC_NRPN_LSB :
867+ ret = fill_rpn (cc , data , channel , true);
842868 cc -> nrpn_set = 1 ;
843869 cc -> cc_nrpn_lsb = val ;
844- return 0 ; // skip
870+ return ret ;
845871 case UMP_CC_DATA :
872+ cc -> cc_data_msb_set = 1 ;
846873 cc -> cc_data_msb = val ;
847- return 0 ; // skip
874+ return fill_rpn ( cc , data , channel , false);
848875 case UMP_CC_BANK_SELECT :
849876 cc -> bank_set = 1 ;
850877 cc -> cc_bank_msb = val ;
@@ -854,11 +881,9 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
854881 cc -> cc_bank_lsb = val ;
855882 return 0 ; // skip
856883 case UMP_CC_DATA_LSB :
884+ cc -> cc_data_lsb_set = 1 ;
857885 cc -> cc_data_lsb = val ;
858- if (!(cc -> rpn_set || cc -> nrpn_set ))
859- return 0 ; // skip
860- fill_rpn (cc , data , channel );
861- return 1 ;
886+ return fill_rpn (cc , data , channel , false);
862887 }
863888
864889 data -> cc .status = status ;
@@ -887,7 +912,7 @@ static int pgm_ev_to_ump_midi2(const struct snd_seq_event *event,
887912 unsigned char status )
888913{
889914 unsigned char channel = event -> data .control .channel & 0x0f ;
890- struct snd_seq_ump_midi2_bank * cc = & dest_port -> midi2_bank [channel ];
915+ struct ump_cvt_to_ump_bank * cc = & dest_port -> midi2_bank [channel ];
891916
892917 data -> pg .status = status ;
893918 data -> pg .channel = channel ;
@@ -924,8 +949,9 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event,
924949{
925950 unsigned char channel = event -> data .control .channel & 0x0f ;
926951 unsigned char index = event -> data .control .param & 0x7f ;
927- struct snd_seq_ump_midi2_bank * cc = & dest_port -> midi2_bank [channel ];
952+ struct ump_cvt_to_ump_bank * cc = & dest_port -> midi2_bank [channel ];
928953 unsigned char msb , lsb ;
954+ int ret ;
929955
930956 msb = (event -> data .control .value >> 7 ) & 0x7f ;
931957 lsb = event -> data .control .value & 0x7f ;
@@ -939,28 +965,27 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event,
939965 cc -> cc_bank_lsb = lsb ;
940966 return 0 ; // skip
941967 case UMP_CC_RPN_MSB :
942- cc -> cc_rpn_msb = msb ;
943- fallthrough ;
944968 case UMP_CC_RPN_LSB :
945- cc -> rpn_set = 1 ;
969+ ret = fill_rpn (cc , data , channel , true);
970+ cc -> cc_rpn_msb = msb ;
946971 cc -> cc_rpn_lsb = lsb ;
947- return 0 ; // skip
972+ cc -> rpn_set = 1 ;
973+ if (cc -> cc_rpn_msb == 0x7f && cc -> cc_rpn_lsb == 0x7f )
974+ reset_rpn (cc );
975+ return ret ;
948976 case UMP_CC_NRPN_MSB :
949- cc -> cc_nrpn_msb = msb ;
950- fallthrough ;
951977 case UMP_CC_NRPN_LSB :
978+ ret = fill_rpn (cc , data , channel , true);
979+ cc -> cc_nrpn_msb = msb ;
952980 cc -> nrpn_set = 1 ;
953981 cc -> cc_nrpn_lsb = lsb ;
954- return 0 ; // skip
982+ return ret ;
955983 case UMP_CC_DATA :
956- cc -> cc_data_msb = msb ;
957- fallthrough ;
958984 case UMP_CC_DATA_LSB :
985+ cc -> cc_data_msb_set = cc -> cc_data_lsb_set = 1 ;
986+ cc -> cc_data_msb = msb ;
959987 cc -> cc_data_lsb = lsb ;
960- if (!(cc -> rpn_set || cc -> nrpn_set ))
961- return 0 ; // skip
962- fill_rpn (cc , data , channel );
963- return 1 ;
988+ return fill_rpn (cc , data , channel , false);
964989 }
965990
966991 data -> cc .status = UMP_MSG_STATUS_CC ;
@@ -1192,44 +1217,53 @@ static int cvt_sysex_to_ump(struct snd_seq_client *dest,
11921217{
11931218 struct snd_seq_ump_event ev_cvt ;
11941219 unsigned char status ;
1195- u8 buf [6 ], * xbuf ;
1220+ u8 buf [8 ], * xbuf ;
11961221 int offset = 0 ;
11971222 int len , err ;
1223+ bool finished = false;
11981224
11991225 if (!snd_seq_ev_is_variable (event ))
12001226 return 0 ;
12011227
12021228 setup_ump_event (& ev_cvt , event );
1203- for (;; ) {
1229+ while (! finished ) {
12041230 len = snd_seq_expand_var_event_at (event , sizeof (buf ), buf , offset );
12051231 if (len <= 0 )
12061232 break ;
1207- if (WARN_ON (len > 6 ))
1233+ if (WARN_ON (len > sizeof ( buf ) ))
12081234 break ;
1209- offset += len ;
1235+
12101236 xbuf = buf ;
1237+ status = UMP_SYSEX_STATUS_CONTINUE ;
1238+ /* truncate the sysex start-marker */
12111239 if (* xbuf == UMP_MIDI1_MSG_SYSEX_START ) {
12121240 status = UMP_SYSEX_STATUS_START ;
1213- xbuf ++ ;
12141241 len -- ;
1215- if (len > 0 && xbuf [len - 1 ] == UMP_MIDI1_MSG_SYSEX_END ) {
1242+ offset ++ ;
1243+ xbuf ++ ;
1244+ }
1245+
1246+ /* if the last of this packet or the 1st byte of the next packet
1247+ * is the end-marker, finish the transfer with this packet
1248+ */
1249+ if (len > 0 && len < 8 &&
1250+ xbuf [len - 1 ] == UMP_MIDI1_MSG_SYSEX_END ) {
1251+ if (status == UMP_SYSEX_STATUS_START )
12161252 status = UMP_SYSEX_STATUS_SINGLE ;
1217- len -- ;
1218- }
1219- } else {
1220- if (xbuf [len - 1 ] == UMP_MIDI1_MSG_SYSEX_END ) {
1253+ else
12211254 status = UMP_SYSEX_STATUS_END ;
1222- len -- ;
1223- } else {
1224- status = UMP_SYSEX_STATUS_CONTINUE ;
1225- }
1255+ len -- ;
1256+ finished = true;
12261257 }
1258+
1259+ len = min (len , 6 );
12271260 fill_sysex7_ump (dest_port , ev_cvt .ump , status , xbuf , len );
12281261 err = __snd_seq_deliver_single_event (dest , dest_port ,
12291262 (struct snd_seq_event * )& ev_cvt ,
12301263 atomic , hop );
12311264 if (err < 0 )
12321265 return err ;
1266+ offset += len ;
12331267 }
12341268 return 0 ;
12351269}
0 commit comments