Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);