^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * gmidi.c -- USB MIDI Gadget Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006 Thumtronics Pty Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Developed for Thumtronics by Grey Innovation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Ben Williamson <ben.williamson@greyinnovation.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This code is based in part on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * USB Audio driver, Copyright (C) 2002 by Takashi Iwai.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Refer to the USB Device Class Definition for MIDI Devices:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * http://www.usb.org/developers/devclass_docs/midi10.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* #define VERBOSE_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/usb/composite.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/usb/gadget.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "u_midi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_AUTHOR("Ben Williamson");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static const char longname[] = "MIDI Gadget";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) USB_GADGET_COMPOSITE_OPTIONS();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int index = SNDRV_DEFAULT_IDX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) module_param(index, int, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static char *id = SNDRV_DEFAULT_STR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) module_param(id, charp, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static unsigned int buflen = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param(buflen, uint, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(buflen, "MIDI buffer length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static unsigned int qlen = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) module_param(qlen, uint, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MODULE_PARM_DESC(qlen, "USB read and write request queue length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static unsigned int in_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) module_param(in_ports, uint, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) MODULE_PARM_DESC(in_ports, "Number of MIDI input ports");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static unsigned int out_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) module_param(out_ports, uint, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Thanks to Grey Innovation for donating this product ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Instead: allocate your own, using normal USB-IF procedures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define DRIVER_VENDOR_NUM 0x17b3 /* Grey Innovation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DRIVER_PRODUCT_NUM 0x0004 /* Linux-USB "MIDI Gadget" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* string IDs are assigned dynamically */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static struct usb_device_descriptor device_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .bLength = USB_DT_DEVICE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .bDescriptorType = USB_DT_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* .bcdUSB = DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .bDeviceClass = USB_CLASS_PER_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* .iManufacturer = DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* .iProduct = DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .bNumConfigurations = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct usb_string strings_dev[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) [USB_GADGET_MANUFACTURER_IDX].s = "Grey Innovation",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) [USB_GADGET_PRODUCT_IDX].s = "MIDI Gadget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) [USB_GADGET_SERIAL_IDX].s = "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [STRING_DESCRIPTION_IDX].s = "MIDI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { } /* end of list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static struct usb_gadget_strings stringtab_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .language = 0x0409, /* en-us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .strings = strings_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct usb_gadget_strings *dev_strings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) &stringtab_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static struct usb_function_instance *fi_midi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static struct usb_function *f_midi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int midi_unbind(struct usb_composite_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) usb_put_function(f_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) usb_put_function_instance(fi_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static struct usb_configuration midi_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .label = "MIDI Gadget",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .bConfigurationValue = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* .iConfiguration = DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .bmAttributes = USB_CONFIG_ATT_ONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int midi_bind_config(struct usb_configuration *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) f_midi = usb_get_function(fi_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (IS_ERR(f_midi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return PTR_ERR(f_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) status = usb_add_function(c, f_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) usb_put_function(f_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int midi_bind(struct usb_composite_dev *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct f_midi_opts *midi_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) fi_midi = usb_get_function_instance("midi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (IS_ERR(fi_midi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return PTR_ERR(fi_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) midi_opts = container_of(fi_midi, struct f_midi_opts, func_inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) midi_opts->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) midi_opts->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) midi_opts->in_ports = in_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) midi_opts->out_ports = out_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) midi_opts->buflen = buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) midi_opts->qlen = qlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) status = usb_string_ids_tab(cdev, strings_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) status = usb_add_config(cdev, &midi_config, midi_bind_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) usb_composite_overwrite_options(cdev, &coverwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pr_info("%s\n", longname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) usb_put_function_instance(fi_midi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct usb_composite_driver midi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .name = longname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .dev = &device_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .strings = dev_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .max_speed = USB_SPEED_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .bind = midi_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .unbind = midi_unbind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) module_usb_composite_driver(midi_driver);