linux/drivers/usb/gadget/function/f_midi.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * f_midi.c -- USB MIDI class function driver
 *
 * Copyright (C) 2006 Thumtronics Pty Ltd.
 * Developed for Thumtronics by Grey Innovation
 * Ben Williamson <[email protected]>
 *
 * Rewritten for the composite framework
 *   Copyright (C) 2011 Daniel Mack <[email protected]>
 *
 * Based on drivers/usb/gadget/f_audio.c,
 *   Copyright (C) 2008 Bryan Wu <[email protected]>
 *   Copyright (C) 2008 Analog Devices, Inc
 *
 * and drivers/usb/gadget/midi.c,
 *   Copyright (C) 2006 Thumtronics Pty Ltd.
 *   Ben Williamson <[email protected]>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>

#include <sound/core.h>
#include <sound/initval.h>
#include <sound/rawmidi.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.h>

#include "u_midi.h"

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

static const char f_midi_shortname[] =;
static const char f_midi_longname[] =;

/*
 * We can only handle 16 cables on one single endpoint, as cable numbers are
 * stored in 4-bit fields. And as the interface currently only holds one
 * single endpoint, this is the maximum number of ports we can allow.
 */
#define MAX_PORTS

/* MIDI message states */
enum {};

/*
 * This is a gadget, and the IN/OUT naming is from the host's perspective.
 * USB -> OUT endpoint -> rawmidi
 * USB <- IN endpoint  <- rawmidi
 */
struct gmidi_in_port {};

struct f_midi {};

static inline struct f_midi *func_to_midi(struct usb_function *f)
{}

static void f_midi_transmit(struct f_midi *midi);
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi);
static void f_midi_free_inst(struct usb_function_instance *f);

DECLARE_UAC_AC_HEADER_DESCRIPTOR} ;
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR} ;
DECLARE_USB_MS_ENDPOINT_DESCRIPTOR} ;

/* B.3.1  Standard AC Interface Descriptor */
static struct usb_interface_descriptor ac_interface_desc =;

/* B.3.2  Class-Specific AC Interface Descriptor */
static struct uac1_ac_header_descriptor_1 ac_header_desc =;

/* B.4.1  Standard MS Interface Descriptor */
static struct usb_interface_descriptor ms_interface_desc =;

/* B.4.2  Class-Specific MS Interface Descriptor */
static struct usb_ms_header_descriptor ms_header_desc =;

/* B.5.1  Standard Bulk OUT Endpoint Descriptor */
static struct usb_endpoint_descriptor bulk_out_desc =;

static struct usb_ss_ep_comp_descriptor bulk_out_ss_comp_desc =;

/* B.5.2  Class-specific MS Bulk OUT Endpoint Descriptor */
static struct usb_ms_endpoint_descriptor_16 ms_out_desc =;

/* B.6.1  Standard Bulk IN Endpoint Descriptor */
static struct usb_endpoint_descriptor bulk_in_desc =;

static struct usb_ss_ep_comp_descriptor bulk_in_ss_comp_desc =;

/* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */
static struct usb_ms_endpoint_descriptor_16 ms_in_desc =;

/* string IDs are assigned dynamically */

#define STRING_FUNC_IDX

static struct usb_string midi_string_defs[] =;

static struct usb_gadget_strings midi_stringtab =;

static struct usb_gadget_strings *midi_strings[] =;

static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
						    unsigned length)
{}

static const uint8_t f_midi_cin_length[] =;

/*
 * Receives a chunk of MIDI data.
 */
static void f_midi_read_data(struct usb_ep *ep, int cable,
			     uint8_t *data, int length)
{}

static void f_midi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
{}

static void
f_midi_complete(struct usb_ep *ep, struct usb_request *req)
{}

static void f_midi_drop_out_substreams(struct f_midi *midi)
{}

static int f_midi_start_ep(struct f_midi *midi,
			   struct usb_function *f,
			   struct usb_ep *ep)
{}

static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{}

static void f_midi_disable(struct usb_function *f)
{}

static int f_midi_snd_free(struct snd_device *device)
{}

/*
 * Converts MIDI commands to USB MIDI packets.
 */
static void f_midi_transmit_byte(struct usb_request *req,
				 struct gmidi_in_port *port, uint8_t b)
{}

static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep)
{}

static void f_midi_transmit(struct f_midi *midi)
{}

static void f_midi_in_work(struct work_struct *work)
{}

static int f_midi_in_open(struct snd_rawmidi_substream *substream)
{}

static int f_midi_in_close(struct snd_rawmidi_substream *substream)
{}

static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up)
{}

static int f_midi_out_open(struct snd_rawmidi_substream *substream)
{}

static int f_midi_out_close(struct snd_rawmidi_substream *substream)
{}

static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up)
{}

static const struct snd_rawmidi_ops gmidi_in_ops =;

static const struct snd_rawmidi_ops gmidi_out_ops =;

static inline void f_midi_unregister_card(struct f_midi *midi)
{}

/* register as a sound "card" */
static int f_midi_register_card(struct f_midi *midi)
{}

/* MIDI function driver setup/binding */

static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
{}

static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item)
{}

static void midi_attr_release(struct config_item *item)
{}

static struct configfs_item_operations midi_item_ops =;

#define F_MIDI_OPT(name, test_limit, limit)

#define F_MIDI_OPT_SIGNED(name, test_limit, limit)

F_MIDI_OPT_SIGNED(index, true, SNDRV_CARDS);
F_MIDI_OPT(buflen, false, 0);
F_MIDI_OPT(qlen, false, 0);
F_MIDI_OPT(in_ports, true, MAX_PORTS);
F_MIDI_OPT(out_ports, true, MAX_PORTS);

static ssize_t f_midi_opts_id_show(struct config_item *item, char *page)
{}

static ssize_t f_midi_opts_id_store(struct config_item *item,
				    const char *page, size_t len)
{}

CONFIGFS_ATTR();

static struct configfs_attribute *midi_attrs[] =;

static const struct config_item_type midi_func_type =;

static void f_midi_free_inst(struct usb_function_instance *f)
{}

static struct usb_function_instance *f_midi_alloc_inst(void)
{}

static void f_midi_free(struct usb_function *f)
{}

static void f_midi_rmidi_free(struct snd_rawmidi *rmidi)
{}

static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{}

static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
{}

DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc);