Skip to content

Commit 37e0e14

Browse files
committed
ALSA: ump: Support UMP Endpoint and Function Block parsing
This patch adds the basic support for UMP Endpoint and UMP Function Block parsing, which are extended in the new UMP v1.1 spec. The patch provides a new helper function to perform the query of the UMP Endpoint information and builds up the UMP blocks based on UMP Function Block information. For the communication over the UMP Endpoint, it opens the rawmidi device once internally, inquiries the UMP Endpoint and Function Block info by sending new UMP Stream messages, and waits for the response for each query. The new UMP spec allows to update the FB info and change its associated groups or its activeness on the fly, too. For catching it, the UMP core keeps watching the incoming UMP messages, and snd_ump_receive() handles the incoming UMP Stream messages to refresh the FB info. Link: https://lore.kernel.org/r/20230612081054.17200-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent e375b8a commit 37e0e14

3 files changed

Lines changed: 684 additions & 0 deletions

File tree

include/sound/ump.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ struct snd_ump_endpoint {
2424
void *private_data;
2525
void (*private_free)(struct snd_ump_endpoint *ump);
2626

27+
/* UMP Stream message processing */
28+
u32 stream_wait_for; /* expected stream message status */
29+
bool stream_finished; /* set when message has been processed */
30+
bool parsed; /* UMP / FB parse finished? */
31+
wait_queue_head_t stream_wait;
32+
struct snd_rawmidi_file stream_rfile;
33+
2734
struct list_head block_list; /* list of snd_ump_block objects */
2835

2936
/* intermediate buffer for UMP input */
@@ -80,6 +87,7 @@ struct snd_ump_block {
8087
int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
8188
int output, int input,
8289
struct snd_ump_endpoint **ump_ret);
90+
int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump);
8391
int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
8492
unsigned int direction, unsigned int first_group,
8593
unsigned int num_groups, struct snd_ump_block **blk_ret);
@@ -109,6 +117,8 @@ enum {
109117
UMP_MSG_TYPE_DATA = 0x03,
110118
UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE = 0x04,
111119
UMP_MSG_TYPE_EXTENDED_DATA = 0x05,
120+
UMP_MSG_TYPE_FLEX_DATA = 0x0d,
121+
UMP_MSG_TYPE_STREAM = 0x0f,
112122
};
113123

114124
/* MIDI 2.0 SysEx / Data Status; same values for both 7-bit and 8-bit SysEx */
@@ -119,6 +129,62 @@ enum {
119129
UMP_SYSEX_STATUS_END = 3,
120130
};
121131

132+
/* UMP Utility Type Status (type 0x0) */
133+
enum {
134+
UMP_UTILITY_MSG_STATUS_NOOP = 0x00,
135+
UMP_UTILITY_MSG_STATUS_JR_CLOCK = 0x01,
136+
UMP_UTILITY_MSG_STATUS_JR_TSTAMP = 0x02,
137+
UMP_UTILITY_MSG_STATUS_DCTPQ = 0x03,
138+
UMP_UTILITY_MSG_STATUS_DC = 0x04,
139+
};
140+
141+
/* UMP Stream Message Status (type 0xf) */
142+
enum {
143+
UMP_STREAM_MSG_STATUS_EP_DISCOVERY = 0x00,
144+
UMP_STREAM_MSG_STATUS_EP_INFO = 0x01,
145+
UMP_STREAM_MSG_STATUS_DEVICE_INFO = 0x02,
146+
UMP_STREAM_MSG_STATUS_EP_NAME = 0x03,
147+
UMP_STREAM_MSG_STATUS_PRODUCT_ID = 0x04,
148+
UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST = 0x05,
149+
UMP_STREAM_MSG_STATUS_STREAM_CFG = 0x06,
150+
UMP_STREAM_MSG_STATUS_FB_DISCOVERY = 0x10,
151+
UMP_STREAM_MSG_STATUS_FB_INFO = 0x11,
152+
UMP_STREAM_MSG_STATUS_FB_NAME = 0x12,
153+
UMP_STREAM_MSG_STATUS_START_CLIP = 0x20,
154+
UMP_STREAM_MSG_STATUS_END_CLIP = 0x21,
155+
};
156+
157+
/* UMP Endpoint Discovery filter bitmap */
158+
enum {
159+
UMP_STREAM_MSG_REQUEST_EP_INFO = (1U << 0),
160+
UMP_STREAM_MSG_REQUEST_DEVICE_INFO = (1U << 1),
161+
UMP_STREAM_MSG_REQUEST_EP_NAME = (1U << 2),
162+
UMP_STREAM_MSG_REQUEST_PRODUCT_ID = (1U << 3),
163+
UMP_STREAM_MSG_REQUEST_STREAM_CFG = (1U << 4),
164+
};
165+
166+
/* UMP Function Block Discovery filter bitmap */
167+
enum {
168+
UMP_STREAM_MSG_REQUEST_FB_INFO = (1U << 0),
169+
UMP_STREAM_MSG_REQUEST_FB_NAME = (1U << 1),
170+
};
171+
172+
/* UMP Endpoint Info capability bits (used for protocol request/notify, too) */
173+
enum {
174+
UMP_STREAM_MSG_EP_INFO_CAP_TXJR = (1U << 0), /* Sending JRTS */
175+
UMP_STREAM_MSG_EP_INFO_CAP_RXJR = (1U << 1), /* Receiving JRTS */
176+
UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 = (1U << 8), /* MIDI 1.0 */
177+
UMP_STREAM_MSG_EP_INFO_CAP_MIDI2 = (1U << 9), /* MIDI 2.0 */
178+
};
179+
180+
/* UMP EP / FB name string format; same as SysEx string handling */
181+
enum {
182+
UMP_STREAM_MSG_FORMAT_SINGLE = 0,
183+
UMP_STREAM_MSG_FORMAT_START = 1,
184+
UMP_STREAM_MSG_FORMAT_CONTINUE = 2,
185+
UMP_STREAM_MSG_FORMAT_END = 3,
186+
};
187+
122188
/*
123189
* Helpers for retrieving / filling bits from UMP
124190
*/
@@ -172,4 +238,21 @@ static inline unsigned char ump_sysex_message_length(u32 data)
172238
return (data >> 16) & 0xf;
173239
}
174240

241+
/* For Stream Messages */
242+
static inline unsigned char ump_stream_message_format(u32 data)
243+
{
244+
return (data >> 26) & 0x03;
245+
}
246+
247+
static inline unsigned int ump_stream_message_status(u32 data)
248+
{
249+
return (data >> 16) & 0x3ff;
250+
}
251+
252+
static inline u32 ump_stream_compose(unsigned char status, unsigned short form)
253+
{
254+
return (UMP_MSG_TYPE_STREAM << 28) | ((u32)form << 26) |
255+
((u32)status << 16);
256+
}
257+
175258
#endif /* __SOUND_UMP_H */

include/sound/ump_msg.h

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,4 +537,229 @@ union snd_ump_midi2_msg {
537537
u32 raw[2];
538538
};
539539

540+
/* UMP Stream Message: Endpoint Discovery (128bit) */
541+
struct snd_ump_stream_msg_ep_discovery {
542+
#ifdef __BIG_ENDIAN_BITFIELD
543+
/* 0 */
544+
u32 type:4;
545+
u32 format:2;
546+
u32 status:10;
547+
u32 ump_version_major:8;
548+
u32 ump_version_minor:8;
549+
/* 1 */
550+
u32 reserved:24;
551+
u32 filter_bitmap:8;
552+
/* 2-3 */
553+
u32 reserved2[2];
554+
#else
555+
/* 0 */
556+
u32 ump_version_minor:8;
557+
u32 ump_version_major:8;
558+
u32 status:10;
559+
u32 format:2;
560+
u32 type:4;
561+
/* 1 */
562+
u32 filter_bitmap:8;
563+
u32 reserved:24;
564+
/* 2-3 */
565+
u32 reserved2[2];
566+
#endif
567+
} __packed;
568+
569+
/* UMP Stream Message: Endpoint Info Notification (128bit) */
570+
struct snd_ump_stream_msg_ep_info {
571+
#ifdef __BIG_ENDIAN_BITFIELD
572+
/* 0 */
573+
u32 type:4;
574+
u32 format:2;
575+
u32 status:10;
576+
u32 ump_version_major:8;
577+
u32 ump_version_minor:8;
578+
/* 1 */
579+
u32 static_function_block:1;
580+
u32 num_function_blocks:7;
581+
u32 reserved:8;
582+
u32 protocol:8;
583+
u32 reserved2:6;
584+
u32 jrts:2;
585+
/* 2-3 */
586+
u32 reserved3[2];
587+
#else
588+
/* 0 */
589+
u32 ump_version_minor:8;
590+
u32 ump_version_major:8;
591+
u32 status:10;
592+
u32 format:2;
593+
u32 type:4;
594+
/* 1 */
595+
u32 jrts:2;
596+
u32 reserved2:6;
597+
u32 protocol:8;
598+
u32 reserved:8;
599+
u32 num_function_blocks:7;
600+
u32 static_function_block:1;
601+
/* 2-3 */
602+
u32 reserved3[2];
603+
#endif
604+
} __packed;
605+
606+
/* UMP Stream Message: Device Info Notification (128bit) */
607+
struct snd_ump_stream_msg_devince_info {
608+
#ifdef __BIG_ENDIAN_BITFIELD
609+
/* 0 */
610+
u32 type:4;
611+
u32 format:2;
612+
u32 status:10;
613+
u32 reserved:16;
614+
/* 1 */
615+
u32 manufacture_id;
616+
/* 2 */
617+
u8 family_lsb;
618+
u8 family_msb;
619+
u8 model_lsb;
620+
u8 model_msb;
621+
/* 3 */
622+
u32 sw_revision;
623+
#else
624+
/* 0 */
625+
u32 reserved:16;
626+
u32 status:10;
627+
u32 format:2;
628+
u32 type:4;
629+
/* 1 */
630+
u32 manufacture_id;
631+
/* 2 */
632+
u8 model_msb;
633+
u8 model_lsb;
634+
u8 family_msb;
635+
u8 family_lsb;
636+
/* 3 */
637+
u32 sw_revision;
638+
#endif
639+
} __packed;
640+
641+
/* UMP Stream Message: Stream Config Request / Notification (128bit) */
642+
struct snd_ump_stream_msg_stream_cfg {
643+
#ifdef __BIG_ENDIAN_BITFIELD
644+
/* 0 */
645+
u32 type:4;
646+
u32 format:2;
647+
u32 status:10;
648+
u32 protocol:8;
649+
u32 reserved:6;
650+
u32 jrts:2;
651+
/* 1-3 */
652+
u32 reserved2[3];
653+
#else
654+
/* 0 */
655+
u32 jrts:2;
656+
u32 reserved:6;
657+
u32 protocol:8;
658+
u32 status:10;
659+
u32 format:2;
660+
u32 type:4;
661+
/* 1-3 */
662+
u32 reserved2[3];
663+
#endif
664+
} __packed;
665+
666+
/* UMP Stream Message: Function Block Discovery (128bit) */
667+
struct snd_ump_stream_msg_fb_discovery {
668+
#ifdef __BIG_ENDIAN_BITFIELD
669+
/* 0 */
670+
u32 type:4;
671+
u32 format:2;
672+
u32 status:10;
673+
u32 function_block_id:8;
674+
u32 filter:8;
675+
/* 1-3 */
676+
u32 reserved[3];
677+
#else
678+
/* 0 */
679+
u32 filter:8;
680+
u32 function_block_id:8;
681+
u32 status:10;
682+
u32 format:2;
683+
u32 type:4;
684+
/* 1-3 */
685+
u32 reserved[3];
686+
#endif
687+
} __packed;
688+
689+
/* UMP Stream Message: Function Block Info Notification (128bit) */
690+
struct snd_ump_stream_msg_fb_info {
691+
#ifdef __BIG_ENDIAN_BITFIELD
692+
/* 0 */
693+
u32 type:4;
694+
u32 format:2;
695+
u32 status:10;
696+
u32 active:1;
697+
u32 function_block_id:7;
698+
u32 reserved:2;
699+
u32 ui_hint:2;
700+
u32 midi_10:2;
701+
u32 direction:2;
702+
/* 1 */
703+
u32 first_group:8;
704+
u32 num_groups:8;
705+
u32 midi_ci_version:8;
706+
u32 sysex8_streams:8;
707+
/* 2-3 */
708+
u32 reserved2[2];
709+
#else
710+
/* 0 */
711+
u32 direction:2;
712+
u32 midi_10:2;
713+
u32 ui_hint:2;
714+
u32 reserved:2;
715+
u32 function_block_id:7;
716+
u32 active:1;
717+
u32 status:10;
718+
u32 format:2;
719+
u32 type:4;
720+
/* 1 */
721+
u32 sysex8_streams:8;
722+
u32 midi_ci_version:8;
723+
u32 num_groups:8;
724+
u32 first_group:8;
725+
/* 2-3 */
726+
u32 reserved2[2];
727+
#endif
728+
} __packed;
729+
730+
/* UMP Stream Message: Function Block Name Notification (128bit) */
731+
struct snd_ump_stream_msg_fb_name {
732+
#ifdef __BIG_ENDIAN_BITFIELD
733+
/* 0 */
734+
u16 type:4;
735+
u16 format:2;
736+
u16 status:10;
737+
u8 function_block_id;
738+
u8 name0;
739+
/* 1-3 */
740+
u8 name[12];
741+
#else
742+
/* 0 */
743+
u8 name0;
744+
u8 function_block_id;
745+
u16 status:10;
746+
u16 format:2;
747+
u16 type:4;
748+
/* 1-3 */
749+
u8 name[12]; // FIXME: byte order
750+
#endif
751+
} __packed;
752+
753+
/* MIDI 2.0 Stream Messages (128bit) */
754+
union snd_ump_stream_msg {
755+
struct snd_ump_stream_msg_ep_discovery ep_discovery;
756+
struct snd_ump_stream_msg_ep_info ep_info;
757+
struct snd_ump_stream_msg_devince_info device_info;
758+
struct snd_ump_stream_msg_stream_cfg stream_cfg;
759+
struct snd_ump_stream_msg_fb_discovery fb_discovery;
760+
struct snd_ump_stream_msg_fb_info fb_info;
761+
struct snd_ump_stream_msg_fb_name fb_name;
762+
u32 raw[4];
763+
};
764+
540765
#endif /* __SOUND_UMP_MSG_H */

0 commit comments

Comments
 (0)