diff options
Diffstat (limited to 'drivers/usb/gadget/function/f_midi2.c')
-rw-r--r-- | drivers/usb/gadget/function/f_midi2.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c index ec8cd7c7bbfc..0a800ba53816 100644 --- a/drivers/usb/gadget/function/f_midi2.c +++ b/drivers/usb/gadget/function/f_midi2.c @@ -15,11 +15,11 @@ #include <sound/ump_convert.h> #include <linux/usb/ch9.h> +#include <linux/usb/func_utils.h> #include <linux/usb/gadget.h> #include <linux/usb/audio.h> #include <linux/usb/midi-v2.h> -#include "u_f.h" #include "u_midi2.h" struct f_midi2; @@ -150,6 +150,9 @@ struct f_midi2 { #define func_to_midi2(f) container_of(f, struct f_midi2, func) +/* convert from MIDI protocol number (1 or 2) to SNDRV_UMP_EP_INFO_PROTO_* */ +#define to_ump_protocol(v) (((v) & 3) << 8) + /* get EP name string */ static const char *ump_ep_name(const struct f_midi2_ep *ep) { @@ -472,7 +475,7 @@ static void reply_ump_stream_ep_info(struct f_midi2_ep *ep) /* reply a UMP EP device info */ static void reply_ump_stream_ep_device(struct f_midi2_ep *ep) { - struct snd_ump_stream_msg_devince_info rep = { + struct snd_ump_stream_msg_device_info rep = { .type = UMP_MSG_TYPE_STREAM, .status = UMP_STREAM_MSG_STATUS_DEVICE_INFO, .manufacture_id = ep->info.manufacturer, @@ -564,8 +567,7 @@ static void reply_ump_stream_ep_config(struct f_midi2_ep *ep) .status = UMP_STREAM_MSG_STATUS_STREAM_CFG, }; - if ((ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK) == - SNDRV_UMP_EP_INFO_PROTO_MIDI2) + if (ep->info.protocol == 2) rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI2 >> 8; else rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 >> 8; @@ -627,25 +629,34 @@ static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data) return; case UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST: if (*data & UMP_STREAM_MSG_EP_INFO_CAP_MIDI2) { - ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI2; + ep->info.protocol = 2; DBG(midi2, "Switching Protocol to MIDI2\n"); } else { - ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1; + ep->info.protocol = 1; DBG(midi2, "Switching Protocol to MIDI1\n"); } - snd_ump_switch_protocol(ep->ump, ep->info.protocol); + snd_ump_switch_protocol(ep->ump, to_ump_protocol(ep->info.protocol)); reply_ump_stream_ep_config(ep); return; case UMP_STREAM_MSG_STATUS_FB_DISCOVERY: if (format) return; // invalid blk = (*data >> 8) & 0xff; - if (blk >= ep->num_blks) - return; - if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) - reply_ump_stream_fb_info(ep, blk); - if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) - reply_ump_stream_fb_name(ep, blk); + if (blk == 0xff) { + /* inquiry for all blocks */ + for (blk = 0; blk < ep->num_blks; blk++) { + if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) + reply_ump_stream_fb_info(ep, blk); + if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) + reply_ump_stream_fb_name(ep, blk); + } + } else if (blk < ep->num_blks) { + /* only the specified block */ + if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) + reply_ump_stream_fb_info(ep, blk); + if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) + reply_ump_stream_fb_name(ep, blk); + } return; } } @@ -1065,7 +1076,8 @@ static void f_midi2_midi1_ep_out_complete(struct usb_ep *usb_ep, group = midi2->out_cable_mapping[cable].group; bytes = midi1_packet_bytes[*buf & 0x0f]; for (c = 0; c < bytes; c++) { - snd_ump_convert_to_ump(cvt, group, ep->info.protocol, + snd_ump_convert_to_ump(cvt, group, + to_ump_protocol(ep->info.protocol), buf[c + 1]); if (cvt->ump_bytes) { snd_ump_receive(ep->ump, cvt->ump, @@ -1273,10 +1285,8 @@ static int f_midi2_set_alt(struct usb_function *fn, unsigned int intf, if (alt == 0) op_mode = MIDI_OP_MODE_MIDI1; - else if (alt == 1) - op_mode = MIDI_OP_MODE_MIDI2; else - op_mode = MIDI_OP_MODE_UNSET; + op_mode = MIDI_OP_MODE_MIDI2; if (midi2->operation_mode == op_mode) return 0; @@ -1375,7 +1385,7 @@ static void assign_block_descriptors(struct f_midi2 *midi2, desc->nNumGroupTrm = b->num_groups; desc->iBlockItem = ep->blks[blk].string_id; - if (ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) + if (ep->info.protocol == 2) desc->bMIDIProtocol = USB_MS_MIDI_PROTO_2_0; else desc->bMIDIProtocol = USB_MS_MIDI_PROTO_1_0_128; @@ -1552,7 +1562,7 @@ static int f_midi2_create_card(struct f_midi2 *midi2) if (midi2->info.static_block) ump->info.flags |= SNDRV_UMP_EP_INFO_STATIC_BLOCKS; ump->info.protocol_caps = (ep->info.protocol_caps & 3) << 8; - ump->info.protocol = (ep->info.protocol & 3) << 8; + ump->info.protocol = to_ump_protocol(ep->info.protocol); ump->info.version = 0x0101; ump->info.family_id = ep->info.family; ump->info.model_id = ep->info.model; @@ -1581,7 +1591,11 @@ static int f_midi2_create_card(struct f_midi2 *midi2) fb->info.midi_ci_version = b->midi_ci_version; fb->info.ui_hint = reverse_dir(b->ui_hint); fb->info.sysex8_streams = b->sysex8_streams; - fb->info.flags |= b->is_midi1; + if (b->is_midi1 < 2) + fb->info.flags |= b->is_midi1; + else + fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 | + SNDRV_UMP_BLOCK_IS_LOWSPEED; strscpy(fb->info.name, ump_fb_name(b), sizeof(fb->info.name)); } @@ -2868,4 +2882,5 @@ static struct usb_function *f_midi2_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(midi2, f_midi2_alloc_inst, f_midi2_alloc); +MODULE_DESCRIPTION("USB MIDI 2.0 class function driver"); MODULE_LICENSE("GPL"); |