#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/ump.h>
#include <sound/ump_msg.h>
#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_midi2.h"
struct f_midi2;
struct f_midi2_ep;
struct f_midi2_usb_ep;
struct f_midi2_req_ctx { … };
struct f_midi2_usb_ep { … };
struct f_midi2_block { … };
struct f_midi2_midi1_port { … };
enum { … };
struct f_midi2_ep { … };
enum { … };
#define gtb_to_str_id(id) …
struct midi1_cable_mapping { … };
enum { … };
struct f_midi2 { … };
#define func_to_midi2(f) …
#define to_ump_protocol(v) …
static const char *ump_ep_name(const struct f_midi2_ep *ep)
{ … }
static const char *ump_product_id(const struct f_midi2_ep *ep)
{ … }
static const char *ump_fb_name(const struct f_midi2_block_info *info)
{ … }
static struct usb_ms20_gr_trm_block_header_descriptor gtb_header_desc = …;
static struct usb_ms20_gr_trm_block_descriptor gtb_desc = …;
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR … } ;
DECLARE_USB_MS_ENDPOINT_DESCRIPTOR … } ;
DECLARE_UAC_AC_HEADER_DESCRIPTOR … } ;
DECLARE_USB_MS20_ENDPOINT_DESCRIPTOR … } ;
#define EP_MAX_PACKET_INT …
static struct usb_interface_descriptor midi2_audio_if_desc = …;
static struct uac1_ac_header_descriptor_1 midi2_audio_class_desc = …;
static struct usb_interface_descriptor midi2_midi1_if_desc = …;
static struct usb_ms_header_descriptor midi2_midi1_class_desc = …;
static struct usb_endpoint_descriptor midi2_midi1_ep_out_desc = …;
static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_out_ss_comp_desc = …;
static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_out_class_desc = …;
static struct usb_endpoint_descriptor midi2_midi1_ep_in_desc = …;
static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_in_ss_comp_desc = …;
static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_in_class_desc = …;
static struct usb_interface_descriptor midi2_midi2_if_desc = …;
static struct usb_ms_header_descriptor midi2_midi2_class_desc = …;
static struct usb_endpoint_descriptor midi2_midi2_ep_out_desc[MAX_UMP_EPS];
static struct usb_ss_ep_comp_descriptor midi2_midi2_ep_out_ss_comp_desc = …;
static struct usb_ms20_endpoint_descriptor_32 midi2_midi2_ep_out_class_desc[MAX_UMP_EPS];
static struct usb_endpoint_descriptor midi2_midi2_ep_in_desc[MAX_UMP_EPS];
static struct usb_ss_ep_comp_descriptor midi2_midi2_ep_in_ss_comp_desc = …;
static struct usb_ms20_endpoint_descriptor_32 midi2_midi2_ep_in_class_desc[MAX_UMP_EPS];
static void *midi2_audio_descs[] = …;
static void *midi2_midi1_descs[] = …;
static void *midi2_midi1_ep_out_descs[] = …;
static void *midi2_midi1_ep_in_descs[] = …;
static void *midi2_midi1_ep_out_ss_descs[] = …;
static void *midi2_midi1_ep_in_ss_descs[] = …;
static void *midi2_midi2_descs[] = …;
static struct usb_request *get_empty_request(struct f_midi2_usb_ep *usb_ep)
{ … }
static void put_empty_request(struct usb_request *req)
{ … }
static int queue_request_ep_raw(struct usb_request *req)
{ … }
static int queue_request_ep_in(struct usb_request *req)
{ … }
static int reply_ep_in(struct f_midi2_ep *ep, const void *buf, int len)
{ … }
static void reply_ump_stream_ep_info(struct f_midi2_ep *ep)
{ … }
static void reply_ump_stream_ep_device(struct f_midi2_ep *ep)
{ … }
#define UMP_STREAM_PKT_BYTES …
#define UMP_STREAM_EP_STR_OFF …
#define UMP_STREAM_FB_STR_OFF …
static void reply_ump_stream_string(struct f_midi2_ep *ep, const u8 *name,
unsigned int type, unsigned int extra,
unsigned int start_ofs)
{ … }
static void reply_ump_stream_ep_name(struct f_midi2_ep *ep)
{ … }
static void reply_ump_stream_ep_pid(struct f_midi2_ep *ep)
{ … }
static void reply_ump_stream_ep_config(struct f_midi2_ep *ep)
{ … }
static void reply_ump_stream_fb_info(struct f_midi2_ep *ep, int blk)
{ … }
static void reply_ump_stream_fb_name(struct f_midi2_ep *ep, unsigned int blk)
{ … }
static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data)
{ … }
static void process_ump(struct f_midi2_ep *ep, const struct usb_request *req)
{ … }
static void f_midi2_ep_out_complete(struct usb_ep *usb_ep,
struct usb_request *req)
{ … }
static void process_ump_transmit(struct f_midi2_ep *ep)
{ … }
static void f_midi2_ep_in_complete(struct usb_ep *usb_ep,
struct usb_request *req)
{ … }
static bool process_midi1_byte(struct f_midi2 *midi2, u8 cable, u8 b,
struct usb_request **req_p)
{ … }
static bool process_midi1_pending_buf(struct f_midi2 *midi2,
struct usb_request **req_p)
{ … }
static void fill_midi1_pending_buf(struct f_midi2 *midi2, u8 cable, u8 *buf,
unsigned int size)
{ … }
static void process_midi1_transmit(struct f_midi2 *midi2)
{ … }
static void f_midi2_midi1_ep_in_complete(struct usb_ep *usb_ep,
struct usb_request *req)
{ … }
static void f_midi2_midi1_ep_out_complete(struct usb_ep *usb_ep,
struct usb_request *req)
{ … }
static int f_midi2_start_ep(struct f_midi2_usb_ep *usb_ep,
struct usb_function *fn)
{ … }
static void f_midi2_drop_reqs(struct f_midi2_usb_ep *usb_ep)
{ … }
static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep)
{ … }
static void f_midi2_free_ep_reqs(struct f_midi2_usb_ep *usb_ep)
{ … }
static int f_midi2_init_ep(struct f_midi2 *midi2, struct f_midi2_ep *ep,
struct f_midi2_usb_ep *usb_ep,
void *desc,
void (*complete)(struct usb_ep *usb_ep,
struct usb_request *req))
{ … }
static void f_midi2_free_ep(struct f_midi2_usb_ep *usb_ep)
{ … }
static void f_midi2_queue_out_reqs(struct f_midi2_usb_ep *usb_ep)
{ … }
static void f_midi2_stop_eps(struct f_midi2_usb_ep *ep_in,
struct f_midi2_usb_ep *ep_out)
{ … }
static int f_midi2_start_eps(struct f_midi2_usb_ep *ep_in,
struct f_midi2_usb_ep *ep_out,
struct usb_function *fn)
{ … }
static int f_midi2_set_alt(struct usb_function *fn, unsigned int intf,
unsigned int alt)
{ … }
static int f_midi2_get_alt(struct usb_function *fn, unsigned int intf)
{ … }
static unsigned int ump_to_usb_dir(unsigned int ump_dir)
{ … }
static void assign_block_descriptors(struct f_midi2 *midi2,
struct usb_request *req,
int max_len)
{ … }
static int f_midi2_setup(struct usb_function *fn,
const struct usb_ctrlrequest *ctrl)
{ … }
static void f_midi2_disable(struct usb_function *fn)
{ … }
static int f_midi2_ump_open(struct snd_ump_endpoint *ump, int dir)
{ … }
static void f_midi2_ump_close(struct snd_ump_endpoint *ump, int dir)
{ … }
static void f_midi2_ump_trigger(struct snd_ump_endpoint *ump, int dir, int up)
{ … }
static void f_midi2_ump_drain(struct snd_ump_endpoint *ump, int dir)
{ … }
static const struct snd_ump_ops f_midi2_ump_ops = …;
static int f_midi2_operation_mode_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int f_midi2_operation_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static const struct snd_kcontrol_new operation_mode_ctl = …;
static void f_midi2_free_card(struct f_midi2 *midi2)
{ … }
static int reverse_dir(int dir)
{ … }
static int f_midi2_create_card(struct f_midi2 *midi2)
{ … }
struct f_midi2_usb_config { … };
static int append_config(struct f_midi2_usb_config *config, void *d)
{ … }
static int append_configs(struct f_midi2_usb_config *config, void **d)
{ … }
static int append_midi1_in_jack(struct f_midi2 *midi2,
struct f_midi2_usb_config *config,
struct midi1_cable_mapping *map,
unsigned int type)
{ … }
static int append_midi1_out_jack(struct f_midi2 *midi2,
struct f_midi2_usb_config *config,
struct midi1_cable_mapping *map,
unsigned int type, unsigned int source)
{ … }
static int f_midi2_create_usb_configs(struct f_midi2 *midi2,
struct f_midi2_usb_config *config,
int speed)
{ … }
static void f_midi2_free_usb_configs(struct f_midi2_usb_config *config)
{ … }
static DEFINE_MUTEX(f_midi2_desc_mutex);
static void fill_midi2_class_desc(struct f_midi2_ep *ep,
struct usb_ms20_endpoint_descriptor_32 *cdesc)
{ … }
static int f_midi2_init_midi2_ep_in(struct f_midi2 *midi2, int index)
{ … }
static int f_midi2_init_midi2_ep_out(struct f_midi2 *midi2, int index)
{ … }
static int f_midi2_bind(struct usb_configuration *c, struct usb_function *f)
{ … }
static void f_midi2_unbind(struct usb_configuration *c, struct usb_function *f)
{ … }
static inline struct f_midi2_opts *to_f_midi2_opts(struct config_item *item)
{ … }
static inline struct f_midi2_ep_opts *
to_f_midi2_ep_opts(struct config_item *item)
{ … }
static inline struct f_midi2_block_opts *
to_f_midi2_block_opts(struct config_item *item)
{ … }
static void make_name_string(char *s)
{ … }
static ssize_t f_midi2_opts_uint_show(struct f_midi2_opts *opts,
u32 val, const char *format, char *page)
{ … }
static ssize_t f_midi2_opts_uint_store(struct f_midi2_opts *opts,
u32 *valp, u32 minval, u32 maxval,
const char *page, size_t len)
{ … }
static ssize_t f_midi2_opts_bool_store(struct f_midi2_opts *opts,
bool *valp, const char *page, size_t len)
{ … }
static ssize_t f_midi2_opts_str_show(struct f_midi2_opts *opts,
const char *str, char *page)
{ … }
static ssize_t f_midi2_opts_str_store(struct f_midi2_opts *opts,
const char **strp, size_t maxlen,
const char *page, size_t len)
{ … }
#define F_MIDI2_BLOCK_OPT(name, format, minval, maxval) …
#define F_MIDI2_BLOCK_BOOL_OPT(name) …
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_OPT(…);
F_MIDI2_BLOCK_BOOL_OPT(…);
static ssize_t f_midi2_block_opts_name_show(struct config_item *item,
char *page)
{ … }
static ssize_t f_midi2_block_opts_name_store(struct config_item *item,
const char *page, size_t len)
{ … }
CONFIGFS_ATTR(…);
static struct configfs_attribute *f_midi2_block_attrs[] = …;
static void f_midi2_block_opts_release(struct config_item *item)
{ … }
static struct configfs_item_operations f_midi2_block_item_ops = …;
static const struct config_item_type f_midi2_block_type = …;
static int f_midi2_block_opts_create(struct f_midi2_ep_opts *ep_opts,
unsigned int blk,
struct f_midi2_block_opts **block_p)
{ … }
static struct config_group *
f_midi2_opts_block_make(struct config_group *group, const char *name)
{ … }
static void
f_midi2_opts_block_drop(struct config_group *group, struct config_item *item)
{ … }
#define F_MIDI2_EP_OPT(name, format, minval, maxval) …
#define F_MIDI2_EP_STR_OPT(name, maxlen) …
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_OPT(…);
F_MIDI2_EP_STR_OPT(…);
F_MIDI2_EP_STR_OPT(…);
static struct configfs_attribute *f_midi2_ep_attrs[] = …;
static void f_midi2_ep_opts_release(struct config_item *item)
{ … }
static struct configfs_item_operations f_midi2_ep_item_ops = …;
static struct configfs_group_operations f_midi2_ep_group_ops = …;
static const struct config_item_type f_midi2_ep_type = …;
static int f_midi2_ep_opts_create(struct f_midi2_opts *opts,
unsigned int index,
struct f_midi2_ep_opts **ep_p)
{ … }
static struct config_group *
f_midi2_opts_ep_make(struct config_group *group, const char *name)
{ … }
static void
f_midi2_opts_ep_drop(struct config_group *group, struct config_item *item)
{ … }
#define F_MIDI2_BOOL_OPT(name) …
F_MIDI2_BOOL_OPT(…);
F_MIDI2_BOOL_OPT(…);
static ssize_t f_midi2_opts_iface_name_show(struct config_item *item,
char *page)
{ … }
static ssize_t f_midi2_opts_iface_name_store(struct config_item *item,
const char *page, size_t len)
{ … }
CONFIGFS_ATTR(…);
static struct configfs_attribute *f_midi2_attrs[] = …;
static void f_midi2_opts_release(struct config_item *item)
{ … }
static struct configfs_item_operations f_midi2_item_ops = …;
static struct configfs_group_operations f_midi2_group_ops = …;
static const struct config_item_type f_midi2_func_type = …;
static void f_midi2_free_inst(struct usb_function_instance *f)
{ … }
static struct usb_function_instance *f_midi2_alloc_inst(void)
{ … }
static void do_f_midi2_free(struct f_midi2 *midi2, struct f_midi2_opts *opts)
{ … }
static void f_midi2_free(struct usb_function *f)
{ … }
static int verify_parameters(struct f_midi2_opts *opts)
{ … }
static void fill_midi1_cable_mapping(struct f_midi2 *midi2,
struct f_midi2_ep *ep,
int blk)
{ … }
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(…) …;
MODULE_LICENSE(…) …;