| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1 | /* | 
|  | 2 | * gmidi.c -- USB MIDI Gadget Driver | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 2006 Thumtronics Pty Ltd. | 
|  | 5 | * Developed for Thumtronics by Grey Innovation | 
|  | 6 | * Ben Williamson <ben.williamson@greyinnovation.com> | 
|  | 7 | * | 
|  | 8 | * This software is distributed under the terms of the GNU General Public | 
|  | 9 | * License ("GPL") version 2, as published by the Free Software Foundation. | 
|  | 10 | * | 
|  | 11 | * This code is based in part on: | 
|  | 12 | * | 
|  | 13 | * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell. | 
|  | 14 | * USB Audio driver, Copyright (C) 2002 by Takashi Iwai. | 
|  | 15 | * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch. | 
|  | 16 | * | 
|  | 17 | * Refer to the USB Device Class Definition for MIDI Devices: | 
|  | 18 | * http://www.usb.org/developers/devclass_docs/midi10.pdf | 
|  | 19 | */ | 
|  | 20 |  | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 21 | /* #define VERBOSE_DEBUG */ | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 22 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 23 | #include <linux/kernel.h> | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 24 | #include <linux/utsname.h> | 
|  | 25 | #include <linux/device.h> | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 26 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 27 | #include <sound/core.h> | 
|  | 28 | #include <sound/initval.h> | 
|  | 29 | #include <sound/rawmidi.h> | 
|  | 30 |  | 
| David Brownell | 5f84813 | 2006-12-16 15:34:53 -0800 | [diff] [blame] | 31 | #include <linux/usb/ch9.h> | 
| David Brownell | 9454a57 | 2007-10-04 18:05:17 -0700 | [diff] [blame] | 32 | #include <linux/usb/gadget.h> | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 33 | #include <linux/usb/audio.h> | 
|  | 34 | #include <linux/usb/midi.h> | 
|  | 35 |  | 
|  | 36 | #include "gadget_chips.h" | 
|  | 37 |  | 
| David Brownell | 77f754c | 2008-08-18 17:42:04 -0700 | [diff] [blame] | 38 |  | 
|  | 39 | /* | 
|  | 40 | * Kbuild is not very cooperative with respect to linking separately | 
|  | 41 | * compiled library objects into one module.  So for now we won't use | 
|  | 42 | * separate compilation ... ensuring init/exit sections work to shrink | 
|  | 43 | * the runtime footprint, and giving us at least some parts of what | 
|  | 44 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | 
|  | 45 | */ | 
|  | 46 | #include "usbstring.c" | 
|  | 47 | #include "config.c" | 
|  | 48 | #include "epautoconf.c" | 
|  | 49 |  | 
|  | 50 | /*-------------------------------------------------------------------------*/ | 
|  | 51 |  | 
|  | 52 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 53 | MODULE_AUTHOR("Ben Williamson"); | 
|  | 54 | MODULE_LICENSE("GPL v2"); | 
|  | 55 |  | 
|  | 56 | #define DRIVER_VERSION "25 Jul 2006" | 
|  | 57 |  | 
|  | 58 | static const char shortname[] = "g_midi"; | 
|  | 59 | static const char longname[] = "MIDI Gadget"; | 
|  | 60 |  | 
|  | 61 | static int index = SNDRV_DEFAULT_IDX1; | 
|  | 62 | static char *id = SNDRV_DEFAULT_STR1; | 
|  | 63 |  | 
|  | 64 | module_param(index, int, 0444); | 
|  | 65 | MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter."); | 
|  | 66 | module_param(id, charp, 0444); | 
|  | 67 | MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter."); | 
|  | 68 |  | 
|  | 69 | /* Some systems will want different product identifers published in the | 
|  | 70 | * device descriptor, either numbers or strings or both.  These string | 
|  | 71 | * parameters are in UTF-8 (superset of ASCII's 7 bit characters). | 
|  | 72 | */ | 
|  | 73 |  | 
|  | 74 | static ushort idVendor; | 
|  | 75 | module_param(idVendor, ushort, S_IRUGO); | 
|  | 76 | MODULE_PARM_DESC(idVendor, "USB Vendor ID"); | 
|  | 77 |  | 
|  | 78 | static ushort idProduct; | 
|  | 79 | module_param(idProduct, ushort, S_IRUGO); | 
|  | 80 | MODULE_PARM_DESC(idProduct, "USB Product ID"); | 
|  | 81 |  | 
|  | 82 | static ushort bcdDevice; | 
|  | 83 | module_param(bcdDevice, ushort, S_IRUGO); | 
|  | 84 | MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); | 
|  | 85 |  | 
|  | 86 | static char *iManufacturer; | 
|  | 87 | module_param(iManufacturer, charp, S_IRUGO); | 
|  | 88 | MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); | 
|  | 89 |  | 
|  | 90 | static char *iProduct; | 
|  | 91 | module_param(iProduct, charp, S_IRUGO); | 
|  | 92 | MODULE_PARM_DESC(iProduct, "USB Product string"); | 
|  | 93 |  | 
|  | 94 | static char *iSerialNumber; | 
|  | 95 | module_param(iSerialNumber, charp, S_IRUGO); | 
|  | 96 | MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); | 
|  | 97 |  | 
|  | 98 | /* | 
|  | 99 | * this version autoconfigures as much as possible, | 
|  | 100 | * which is reasonable for most "bulk-only" drivers. | 
|  | 101 | */ | 
|  | 102 | static const char *EP_IN_NAME; | 
|  | 103 | static const char *EP_OUT_NAME; | 
|  | 104 |  | 
|  | 105 |  | 
|  | 106 | /* big enough to hold our biggest descriptor */ | 
|  | 107 | #define USB_BUFSIZ 256 | 
|  | 108 |  | 
|  | 109 |  | 
|  | 110 | /* This is a gadget, and the IN/OUT naming is from the host's perspective. | 
|  | 111 | USB -> OUT endpoint -> rawmidi | 
|  | 112 | USB <- IN endpoint  <- rawmidi */ | 
|  | 113 | struct gmidi_in_port { | 
|  | 114 | struct gmidi_device* dev; | 
|  | 115 | int active; | 
|  | 116 | uint8_t cable;		/* cable number << 4 */ | 
|  | 117 | uint8_t state; | 
|  | 118 | #define STATE_UNKNOWN	0 | 
|  | 119 | #define STATE_1PARAM	1 | 
|  | 120 | #define STATE_2PARAM_1	2 | 
|  | 121 | #define STATE_2PARAM_2	3 | 
|  | 122 | #define STATE_SYSEX_0	4 | 
|  | 123 | #define STATE_SYSEX_1	5 | 
|  | 124 | #define STATE_SYSEX_2	6 | 
|  | 125 | uint8_t data[2]; | 
|  | 126 | }; | 
|  | 127 |  | 
|  | 128 | struct gmidi_device { | 
|  | 129 | spinlock_t		lock; | 
|  | 130 | struct usb_gadget	*gadget; | 
|  | 131 | struct usb_request	*req;		/* for control responses */ | 
|  | 132 | u8			config; | 
|  | 133 | struct usb_ep		*in_ep, *out_ep; | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 134 | struct snd_card		*card; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 135 | struct snd_rawmidi	*rmidi; | 
|  | 136 | struct snd_rawmidi_substream *in_substream; | 
|  | 137 | struct snd_rawmidi_substream *out_substream; | 
|  | 138 |  | 
|  | 139 | /* For the moment we only support one port in | 
|  | 140 | each direction, but in_port is kept as a | 
|  | 141 | separate struct so we can have more later. */ | 
|  | 142 | struct gmidi_in_port	in_port; | 
|  | 143 | unsigned long		out_triggered; | 
|  | 144 | struct tasklet_struct	tasklet; | 
|  | 145 | }; | 
|  | 146 |  | 
|  | 147 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); | 
|  | 148 |  | 
|  | 149 |  | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 150 | #define DBG(d, fmt, args...) \ | 
|  | 151 | dev_dbg(&(d)->gadget->dev , fmt , ## args) | 
|  | 152 | #define VDBG(d, fmt, args...) \ | 
|  | 153 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 
|  | 154 | #define ERROR(d, fmt, args...) \ | 
|  | 155 | dev_err(&(d)->gadget->dev , fmt , ## args) | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 156 | #define INFO(d, fmt, args...) \ | 
|  | 157 | dev_info(&(d)->gadget->dev , fmt , ## args) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 158 |  | 
|  | 159 |  | 
|  | 160 | static unsigned buflen = 256; | 
|  | 161 | static unsigned qlen = 32; | 
|  | 162 |  | 
|  | 163 | module_param(buflen, uint, S_IRUGO); | 
|  | 164 | module_param(qlen, uint, S_IRUGO); | 
|  | 165 |  | 
|  | 166 |  | 
|  | 167 | /* Thanks to Grey Innovation for donating this product ID. | 
|  | 168 | * | 
|  | 169 | * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!! | 
|  | 170 | * Instead:  allocate your own, using normal USB-IF procedures. | 
|  | 171 | */ | 
|  | 172 | #define DRIVER_VENDOR_NUM	0x17b3		/* Grey Innovation */ | 
|  | 173 | #define DRIVER_PRODUCT_NUM	0x0004		/* Linux-USB "MIDI Gadget" */ | 
|  | 174 |  | 
|  | 175 |  | 
|  | 176 | /* | 
|  | 177 | * DESCRIPTORS ... most are static, but strings and (full) | 
|  | 178 | * configuration descriptors are built on demand. | 
|  | 179 | */ | 
|  | 180 |  | 
|  | 181 | #define STRING_MANUFACTURER	25 | 
|  | 182 | #define STRING_PRODUCT		42 | 
|  | 183 | #define STRING_SERIAL		101 | 
|  | 184 | #define STRING_MIDI_GADGET	250 | 
|  | 185 |  | 
|  | 186 | /* We only have the one configuration, it's number 1. */ | 
|  | 187 | #define	GMIDI_CONFIG		1 | 
|  | 188 |  | 
|  | 189 | /* We have two interfaces- AudioControl and MIDIStreaming */ | 
|  | 190 | #define GMIDI_AC_INTERFACE	0 | 
|  | 191 | #define GMIDI_MS_INTERFACE	1 | 
|  | 192 | #define GMIDI_NUM_INTERFACES	2 | 
|  | 193 |  | 
|  | 194 | DECLARE_USB_AC_HEADER_DESCRIPTOR(1); | 
|  | 195 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | 
|  | 196 | DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); | 
|  | 197 |  | 
|  | 198 | /* B.1  Device Descriptor */ | 
|  | 199 | static struct usb_device_descriptor device_desc = { | 
|  | 200 | .bLength =		USB_DT_DEVICE_SIZE, | 
|  | 201 | .bDescriptorType =	USB_DT_DEVICE, | 
| Harvey Harrison | 551509d | 2009-02-11 14:11:36 -0800 | [diff] [blame] | 202 | .bcdUSB =		cpu_to_le16(0x0200), | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 203 | .bDeviceClass =		USB_CLASS_PER_INTERFACE, | 
| Harvey Harrison | 551509d | 2009-02-11 14:11:36 -0800 | [diff] [blame] | 204 | .idVendor =		cpu_to_le16(DRIVER_VENDOR_NUM), | 
|  | 205 | .idProduct =		cpu_to_le16(DRIVER_PRODUCT_NUM), | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 206 | .iManufacturer =	STRING_MANUFACTURER, | 
|  | 207 | .iProduct =		STRING_PRODUCT, | 
|  | 208 | .bNumConfigurations =	1, | 
|  | 209 | }; | 
|  | 210 |  | 
|  | 211 | /* B.2  Configuration Descriptor */ | 
|  | 212 | static struct usb_config_descriptor config_desc = { | 
|  | 213 | .bLength =		USB_DT_CONFIG_SIZE, | 
|  | 214 | .bDescriptorType =	USB_DT_CONFIG, | 
|  | 215 | /* compute wTotalLength on the fly */ | 
|  | 216 | .bNumInterfaces =	GMIDI_NUM_INTERFACES, | 
|  | 217 | .bConfigurationValue =	GMIDI_CONFIG, | 
|  | 218 | .iConfiguration =	STRING_MIDI_GADGET, | 
|  | 219 | /* | 
|  | 220 | * FIXME: When embedding this driver in a device, | 
|  | 221 | * these need to be set to reflect the actual | 
|  | 222 | * power properties of the device. Is it selfpowered? | 
|  | 223 | */ | 
|  | 224 | .bmAttributes =		USB_CONFIG_ATT_ONE, | 
| David Brownell | 36e893d | 2008-09-12 09:39:06 -0700 | [diff] [blame] | 225 | .bMaxPower =		CONFIG_USB_GADGET_VBUS_DRAW / 2, | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 226 | }; | 
|  | 227 |  | 
|  | 228 | /* B.3.1  Standard AC Interface Descriptor */ | 
|  | 229 | static const struct usb_interface_descriptor ac_interface_desc = { | 
|  | 230 | .bLength =		USB_DT_INTERFACE_SIZE, | 
|  | 231 | .bDescriptorType =	USB_DT_INTERFACE, | 
|  | 232 | .bInterfaceNumber =	GMIDI_AC_INTERFACE, | 
|  | 233 | .bNumEndpoints =	0, | 
|  | 234 | .bInterfaceClass =	USB_CLASS_AUDIO, | 
|  | 235 | .bInterfaceSubClass =	USB_SUBCLASS_AUDIOCONTROL, | 
|  | 236 | .iInterface =		STRING_MIDI_GADGET, | 
|  | 237 | }; | 
|  | 238 |  | 
|  | 239 | /* B.3.2  Class-Specific AC Interface Descriptor */ | 
|  | 240 | static const struct usb_ac_header_descriptor_1 ac_header_desc = { | 
|  | 241 | .bLength =		USB_DT_AC_HEADER_SIZE(1), | 
|  | 242 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 243 | .bDescriptorSubtype =	USB_MS_HEADER, | 
| Harvey Harrison | 551509d | 2009-02-11 14:11:36 -0800 | [diff] [blame] | 244 | .bcdADC =		cpu_to_le16(0x0100), | 
|  | 245 | .wTotalLength =		cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 246 | .bInCollection =	1, | 
|  | 247 | .baInterfaceNr = { | 
|  | 248 | [0] =		GMIDI_MS_INTERFACE, | 
|  | 249 | } | 
|  | 250 | }; | 
|  | 251 |  | 
|  | 252 | /* B.4.1  Standard MS Interface Descriptor */ | 
|  | 253 | static const struct usb_interface_descriptor ms_interface_desc = { | 
|  | 254 | .bLength =		USB_DT_INTERFACE_SIZE, | 
|  | 255 | .bDescriptorType =	USB_DT_INTERFACE, | 
|  | 256 | .bInterfaceNumber =	GMIDI_MS_INTERFACE, | 
|  | 257 | .bNumEndpoints =	2, | 
|  | 258 | .bInterfaceClass =	USB_CLASS_AUDIO, | 
|  | 259 | .bInterfaceSubClass =	USB_SUBCLASS_MIDISTREAMING, | 
|  | 260 | .iInterface =		STRING_MIDI_GADGET, | 
|  | 261 | }; | 
|  | 262 |  | 
|  | 263 | /* B.4.2  Class-Specific MS Interface Descriptor */ | 
|  | 264 | static const struct usb_ms_header_descriptor ms_header_desc = { | 
|  | 265 | .bLength =		USB_DT_MS_HEADER_SIZE, | 
|  | 266 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 267 | .bDescriptorSubtype =	USB_MS_HEADER, | 
| Harvey Harrison | 551509d | 2009-02-11 14:11:36 -0800 | [diff] [blame] | 268 | .bcdMSC =		cpu_to_le16(0x0100), | 
|  | 269 | .wTotalLength =		cpu_to_le16(USB_DT_MS_HEADER_SIZE | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 270 | + 2*USB_DT_MIDI_IN_SIZE | 
| Al Viro | fd05e72 | 2008-04-28 07:00:16 +0100 | [diff] [blame] | 271 | + 2*USB_DT_MIDI_OUT_SIZE(1)), | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 272 | }; | 
|  | 273 |  | 
|  | 274 | #define JACK_IN_EMB	1 | 
|  | 275 | #define JACK_IN_EXT	2 | 
|  | 276 | #define JACK_OUT_EMB	3 | 
|  | 277 | #define JACK_OUT_EXT	4 | 
|  | 278 |  | 
|  | 279 | /* B.4.3  MIDI IN Jack Descriptors */ | 
|  | 280 | static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = { | 
|  | 281 | .bLength =		USB_DT_MIDI_IN_SIZE, | 
|  | 282 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 283 | .bDescriptorSubtype =	USB_MS_MIDI_IN_JACK, | 
|  | 284 | .bJackType =		USB_MS_EMBEDDED, | 
|  | 285 | .bJackID =		JACK_IN_EMB, | 
|  | 286 | }; | 
|  | 287 |  | 
|  | 288 | static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = { | 
|  | 289 | .bLength =		USB_DT_MIDI_IN_SIZE, | 
|  | 290 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 291 | .bDescriptorSubtype =	USB_MS_MIDI_IN_JACK, | 
|  | 292 | .bJackType =		USB_MS_EXTERNAL, | 
|  | 293 | .bJackID =		JACK_IN_EXT, | 
|  | 294 | }; | 
|  | 295 |  | 
|  | 296 | /* B.4.4  MIDI OUT Jack Descriptors */ | 
|  | 297 | static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = { | 
|  | 298 | .bLength =		USB_DT_MIDI_OUT_SIZE(1), | 
|  | 299 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 300 | .bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK, | 
|  | 301 | .bJackType =		USB_MS_EMBEDDED, | 
|  | 302 | .bJackID =		JACK_OUT_EMB, | 
|  | 303 | .bNrInputPins =		1, | 
|  | 304 | .pins = { | 
|  | 305 | [0] = { | 
|  | 306 | .baSourceID =	JACK_IN_EXT, | 
|  | 307 | .baSourcePin =	1, | 
|  | 308 | } | 
|  | 309 | } | 
|  | 310 | }; | 
|  | 311 |  | 
|  | 312 | static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = { | 
|  | 313 | .bLength =		USB_DT_MIDI_OUT_SIZE(1), | 
|  | 314 | .bDescriptorType =	USB_DT_CS_INTERFACE, | 
|  | 315 | .bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK, | 
|  | 316 | .bJackType =		USB_MS_EXTERNAL, | 
|  | 317 | .bJackID =		JACK_OUT_EXT, | 
|  | 318 | .bNrInputPins =		1, | 
|  | 319 | .pins = { | 
|  | 320 | [0] = { | 
|  | 321 | .baSourceID =	JACK_IN_EMB, | 
|  | 322 | .baSourcePin =	1, | 
|  | 323 | } | 
|  | 324 | } | 
|  | 325 | }; | 
|  | 326 |  | 
|  | 327 | /* B.5.1  Standard Bulk OUT Endpoint Descriptor */ | 
|  | 328 | static struct usb_endpoint_descriptor bulk_out_desc = { | 
|  | 329 | .bLength =		USB_DT_ENDPOINT_AUDIO_SIZE, | 
|  | 330 | .bDescriptorType =	USB_DT_ENDPOINT, | 
|  | 331 | .bEndpointAddress =	USB_DIR_OUT, | 
|  | 332 | .bmAttributes =		USB_ENDPOINT_XFER_BULK, | 
|  | 333 | }; | 
|  | 334 |  | 
|  | 335 | /* B.5.2  Class-specific MS Bulk OUT Endpoint Descriptor */ | 
|  | 336 | static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = { | 
|  | 337 | .bLength =		USB_DT_MS_ENDPOINT_SIZE(1), | 
|  | 338 | .bDescriptorType =	USB_DT_CS_ENDPOINT, | 
|  | 339 | .bDescriptorSubtype =	USB_MS_GENERAL, | 
|  | 340 | .bNumEmbMIDIJack =	1, | 
|  | 341 | .baAssocJackID = { | 
|  | 342 | [0] =		JACK_IN_EMB, | 
|  | 343 | } | 
|  | 344 | }; | 
|  | 345 |  | 
|  | 346 | /* B.6.1  Standard Bulk IN Endpoint Descriptor */ | 
|  | 347 | static struct usb_endpoint_descriptor bulk_in_desc = { | 
|  | 348 | .bLength =		USB_DT_ENDPOINT_AUDIO_SIZE, | 
|  | 349 | .bDescriptorType =	USB_DT_ENDPOINT, | 
|  | 350 | .bEndpointAddress =	USB_DIR_IN, | 
|  | 351 | .bmAttributes =		USB_ENDPOINT_XFER_BULK, | 
|  | 352 | }; | 
|  | 353 |  | 
|  | 354 | /* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */ | 
|  | 355 | static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = { | 
|  | 356 | .bLength =		USB_DT_MS_ENDPOINT_SIZE(1), | 
|  | 357 | .bDescriptorType =	USB_DT_CS_ENDPOINT, | 
|  | 358 | .bDescriptorSubtype =	USB_MS_GENERAL, | 
|  | 359 | .bNumEmbMIDIJack =	1, | 
|  | 360 | .baAssocJackID = { | 
|  | 361 | [0] =		JACK_OUT_EMB, | 
|  | 362 | } | 
|  | 363 | }; | 
|  | 364 |  | 
|  | 365 | static const struct usb_descriptor_header *gmidi_function [] = { | 
|  | 366 | (struct usb_descriptor_header *)&ac_interface_desc, | 
|  | 367 | (struct usb_descriptor_header *)&ac_header_desc, | 
|  | 368 | (struct usb_descriptor_header *)&ms_interface_desc, | 
|  | 369 |  | 
|  | 370 | (struct usb_descriptor_header *)&ms_header_desc, | 
|  | 371 | (struct usb_descriptor_header *)&jack_in_emb_desc, | 
|  | 372 | (struct usb_descriptor_header *)&jack_in_ext_desc, | 
|  | 373 | (struct usb_descriptor_header *)&jack_out_emb_desc, | 
|  | 374 | (struct usb_descriptor_header *)&jack_out_ext_desc, | 
|  | 375 | /* If you add more jacks, update ms_header_desc.wTotalLength */ | 
|  | 376 |  | 
|  | 377 | (struct usb_descriptor_header *)&bulk_out_desc, | 
|  | 378 | (struct usb_descriptor_header *)&ms_out_desc, | 
|  | 379 | (struct usb_descriptor_header *)&bulk_in_desc, | 
|  | 380 | (struct usb_descriptor_header *)&ms_in_desc, | 
|  | 381 | NULL, | 
|  | 382 | }; | 
|  | 383 |  | 
|  | 384 | static char manufacturer[50]; | 
|  | 385 | static char product_desc[40] = "MIDI Gadget"; | 
|  | 386 | static char serial_number[20]; | 
|  | 387 |  | 
|  | 388 | /* static strings, in UTF-8 */ | 
|  | 389 | static struct usb_string strings [] = { | 
|  | 390 | { STRING_MANUFACTURER, manufacturer, }, | 
|  | 391 | { STRING_PRODUCT, product_desc, }, | 
|  | 392 | { STRING_SERIAL, serial_number, }, | 
|  | 393 | { STRING_MIDI_GADGET, longname, }, | 
|  | 394 | {  }			/* end of list */ | 
|  | 395 | }; | 
|  | 396 |  | 
|  | 397 | static struct usb_gadget_strings stringtab = { | 
|  | 398 | .language	= 0x0409,	/* en-us */ | 
|  | 399 | .strings	= strings, | 
|  | 400 | }; | 
|  | 401 |  | 
|  | 402 | static int config_buf(struct usb_gadget *gadget, | 
|  | 403 | u8 *buf, u8 type, unsigned index) | 
|  | 404 | { | 
|  | 405 | int len; | 
|  | 406 |  | 
|  | 407 | /* only one configuration */ | 
|  | 408 | if (index != 0) { | 
|  | 409 | return -EINVAL; | 
|  | 410 | } | 
|  | 411 | len = usb_gadget_config_buf(&config_desc, | 
|  | 412 | buf, USB_BUFSIZ, gmidi_function); | 
|  | 413 | if (len < 0) { | 
|  | 414 | return len; | 
|  | 415 | } | 
|  | 416 | ((struct usb_config_descriptor *)buf)->bDescriptorType = type; | 
|  | 417 | return len; | 
|  | 418 | } | 
|  | 419 |  | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 420 | static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 421 | { | 
|  | 422 | struct usb_request	*req; | 
|  | 423 |  | 
|  | 424 | req = usb_ep_alloc_request(ep, GFP_ATOMIC); | 
|  | 425 | if (req) { | 
|  | 426 | req->length = length; | 
|  | 427 | req->buf = kmalloc(length, GFP_ATOMIC); | 
|  | 428 | if (!req->buf) { | 
|  | 429 | usb_ep_free_request(ep, req); | 
|  | 430 | req = NULL; | 
|  | 431 | } | 
|  | 432 | } | 
|  | 433 | return req; | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 | static void free_ep_req(struct usb_ep *ep, struct usb_request *req) | 
|  | 437 | { | 
|  | 438 | kfree(req->buf); | 
|  | 439 | usb_ep_free_request(ep, req); | 
|  | 440 | } | 
|  | 441 |  | 
|  | 442 | static const uint8_t gmidi_cin_length[] = { | 
|  | 443 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | 
|  | 444 | }; | 
|  | 445 |  | 
|  | 446 | /* | 
|  | 447 | * Receives a chunk of MIDI data. | 
|  | 448 | */ | 
|  | 449 | static void gmidi_read_data(struct usb_ep *ep, int cable, | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 450 | uint8_t *data, int length) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 451 | { | 
|  | 452 | struct gmidi_device *dev = ep->driver_data; | 
|  | 453 | /* cable is ignored, because for now we only have one. */ | 
|  | 454 |  | 
|  | 455 | if (!dev->out_substream) { | 
|  | 456 | /* Nobody is listening - throw it on the floor. */ | 
|  | 457 | return; | 
|  | 458 | } | 
|  | 459 | if (!test_bit(dev->out_substream->number, &dev->out_triggered)) { | 
|  | 460 | return; | 
|  | 461 | } | 
|  | 462 | snd_rawmidi_receive(dev->out_substream, data, length); | 
|  | 463 | } | 
|  | 464 |  | 
|  | 465 | static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req) | 
|  | 466 | { | 
|  | 467 | unsigned i; | 
|  | 468 | u8 *buf = req->buf; | 
|  | 469 |  | 
|  | 470 | for (i = 0; i + 3 < req->actual; i += 4) { | 
|  | 471 | if (buf[i] != 0) { | 
|  | 472 | int cable = buf[i] >> 4; | 
|  | 473 | int length = gmidi_cin_length[buf[i] & 0x0f]; | 
|  | 474 | gmidi_read_data(ep, cable, &buf[i + 1], length); | 
|  | 475 | } | 
|  | 476 | } | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) | 
|  | 480 | { | 
|  | 481 | struct gmidi_device *dev = ep->driver_data; | 
|  | 482 | int status = req->status; | 
|  | 483 |  | 
|  | 484 | switch (status) { | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 485 | case 0:				/* normal completion */ | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 486 | if (ep == dev->out_ep) { | 
|  | 487 | /* we received stuff. | 
|  | 488 | req is queued again, below */ | 
|  | 489 | gmidi_handle_out_data(ep, req); | 
|  | 490 | } else if (ep == dev->in_ep) { | 
|  | 491 | /* our transmit completed. | 
|  | 492 | see if there's more to go. | 
|  | 493 | gmidi_transmit eats req, don't queue it again. */ | 
|  | 494 | gmidi_transmit(dev, req); | 
|  | 495 | return; | 
|  | 496 | } | 
|  | 497 | break; | 
|  | 498 |  | 
|  | 499 | /* this endpoint is normally active while we're configured */ | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 500 | case -ECONNABORTED:		/* hardware forced ep reset */ | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 501 | case -ECONNRESET:		/* request dequeued */ | 
|  | 502 | case -ESHUTDOWN:		/* disconnect from host */ | 
|  | 503 | VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, | 
|  | 504 | req->actual, req->length); | 
|  | 505 | if (ep == dev->out_ep) { | 
|  | 506 | gmidi_handle_out_data(ep, req); | 
|  | 507 | } | 
|  | 508 | free_ep_req(ep, req); | 
|  | 509 | return; | 
|  | 510 |  | 
|  | 511 | case -EOVERFLOW:		/* buffer overrun on read means that | 
|  | 512 | * we didn't provide a big enough | 
|  | 513 | * buffer. | 
|  | 514 | */ | 
|  | 515 | default: | 
|  | 516 | DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, | 
|  | 517 | status, req->actual, req->length); | 
|  | 518 | break; | 
|  | 519 | case -EREMOTEIO:		/* short read */ | 
|  | 520 | break; | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | status = usb_ep_queue(ep, req, GFP_ATOMIC); | 
|  | 524 | if (status) { | 
|  | 525 | ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n", | 
|  | 526 | ep->name, req->length, status); | 
|  | 527 | usb_ep_set_halt(ep); | 
|  | 528 | /* FIXME recover later ... somehow */ | 
|  | 529 | } | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags) | 
|  | 533 | { | 
|  | 534 | int err = 0; | 
|  | 535 | struct usb_request *req; | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 536 | struct usb_ep *ep; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 537 | unsigned i; | 
|  | 538 |  | 
|  | 539 | err = usb_ep_enable(dev->in_ep, &bulk_in_desc); | 
|  | 540 | if (err) { | 
|  | 541 | ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err); | 
|  | 542 | goto fail; | 
|  | 543 | } | 
|  | 544 | dev->in_ep->driver_data = dev; | 
|  | 545 |  | 
|  | 546 | err = usb_ep_enable(dev->out_ep, &bulk_out_desc); | 
|  | 547 | if (err) { | 
|  | 548 | ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err); | 
|  | 549 | goto fail; | 
|  | 550 | } | 
|  | 551 | dev->out_ep->driver_data = dev; | 
|  | 552 |  | 
|  | 553 | /* allocate a bunch of read buffers and queue them all at once. */ | 
|  | 554 | ep = dev->out_ep; | 
|  | 555 | for (i = 0; i < qlen && err == 0; i++) { | 
|  | 556 | req = alloc_ep_req(ep, buflen); | 
|  | 557 | if (req) { | 
|  | 558 | req->complete = gmidi_complete; | 
|  | 559 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | 
|  | 560 | if (err) { | 
|  | 561 | DBG(dev, "%s queue req: %d\n", ep->name, err); | 
|  | 562 | } | 
|  | 563 | } else { | 
|  | 564 | err = -ENOMEM; | 
|  | 565 | } | 
|  | 566 | } | 
|  | 567 | fail: | 
|  | 568 | /* caller is responsible for cleanup on error */ | 
|  | 569 | return err; | 
|  | 570 | } | 
|  | 571 |  | 
|  | 572 |  | 
|  | 573 | static void gmidi_reset_config(struct gmidi_device *dev) | 
|  | 574 | { | 
|  | 575 | if (dev->config == 0) { | 
|  | 576 | return; | 
|  | 577 | } | 
|  | 578 |  | 
|  | 579 | DBG(dev, "reset config\n"); | 
|  | 580 |  | 
|  | 581 | /* just disable endpoints, forcing completion of pending i/o. | 
|  | 582 | * all our completion handlers free their requests in this case. | 
|  | 583 | */ | 
|  | 584 | usb_ep_disable(dev->in_ep); | 
|  | 585 | usb_ep_disable(dev->out_ep); | 
|  | 586 | dev->config = 0; | 
|  | 587 | } | 
|  | 588 |  | 
|  | 589 | /* change our operational config.  this code must agree with the code | 
|  | 590 | * that returns config descriptors, and altsetting code. | 
|  | 591 | * | 
|  | 592 | * it's also responsible for power management interactions. some | 
|  | 593 | * configurations might not work with our current power sources. | 
|  | 594 | * | 
|  | 595 | * note that some device controller hardware will constrain what this | 
|  | 596 | * code can do, perhaps by disallowing more than one configuration or | 
|  | 597 | * by limiting configuration choices (like the pxa2xx). | 
|  | 598 | */ | 
|  | 599 | static int | 
|  | 600 | gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) | 
|  | 601 | { | 
|  | 602 | int result = 0; | 
|  | 603 | struct usb_gadget *gadget = dev->gadget; | 
|  | 604 |  | 
|  | 605 | #if 0 | 
|  | 606 | /* FIXME */ | 
|  | 607 | /* Hacking this bit out fixes a bug where on receipt of two | 
|  | 608 | USB_REQ_SET_CONFIGURATION messages, we end up with no | 
|  | 609 | buffered OUT requests waiting for data. This is clearly | 
|  | 610 | hiding a bug elsewhere, because if the config didn't | 
|  | 611 | change then we really shouldn't do anything. */ | 
|  | 612 | /* Having said that, when we do "change" from config 1 | 
|  | 613 | to config 1, we at least gmidi_reset_config() which | 
|  | 614 | clears out any requests on endpoints, so it's not like | 
|  | 615 | we leak or anything. */ | 
|  | 616 | if (number == dev->config) { | 
|  | 617 | return 0; | 
|  | 618 | } | 
|  | 619 | #endif | 
|  | 620 |  | 
|  | 621 | if (gadget_is_sa1100(gadget) && dev->config) { | 
|  | 622 | /* tx fifo is full, but we can't clear it...*/ | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 623 | ERROR(dev, "can't change configurations\n"); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 624 | return -ESPIPE; | 
|  | 625 | } | 
|  | 626 | gmidi_reset_config(dev); | 
|  | 627 |  | 
|  | 628 | switch (number) { | 
|  | 629 | case GMIDI_CONFIG: | 
|  | 630 | result = set_gmidi_config(dev, gfp_flags); | 
|  | 631 | break; | 
|  | 632 | default: | 
|  | 633 | result = -EINVAL; | 
|  | 634 | /* FALL THROUGH */ | 
|  | 635 | case 0: | 
|  | 636 | return result; | 
|  | 637 | } | 
|  | 638 |  | 
|  | 639 | if (!result && (!dev->in_ep || !dev->out_ep)) { | 
|  | 640 | result = -ENODEV; | 
|  | 641 | } | 
|  | 642 | if (result) { | 
|  | 643 | gmidi_reset_config(dev); | 
|  | 644 | } else { | 
|  | 645 | char *speed; | 
|  | 646 |  | 
|  | 647 | switch (gadget->speed) { | 
|  | 648 | case USB_SPEED_LOW:	speed = "low"; break; | 
|  | 649 | case USB_SPEED_FULL:	speed = "full"; break; | 
|  | 650 | case USB_SPEED_HIGH:	speed = "high"; break; | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 651 | default:		speed = "?"; break; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 652 | } | 
|  | 653 |  | 
|  | 654 | dev->config = number; | 
|  | 655 | INFO(dev, "%s speed\n", speed); | 
|  | 656 | } | 
|  | 657 | return result; | 
|  | 658 | } | 
|  | 659 |  | 
|  | 660 |  | 
|  | 661 | static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req) | 
|  | 662 | { | 
|  | 663 | if (req->status || req->actual != req->length) { | 
|  | 664 | DBG((struct gmidi_device *) ep->driver_data, | 
|  | 665 | "setup complete --> %d, %d/%d\n", | 
|  | 666 | req->status, req->actual, req->length); | 
|  | 667 | } | 
|  | 668 | } | 
|  | 669 |  | 
|  | 670 | /* | 
|  | 671 | * The setup() callback implements all the ep0 functionality that's | 
|  | 672 | * not handled lower down, in hardware or the hardware driver (like | 
|  | 673 | * device and endpoint feature flags, and their status).  It's all | 
|  | 674 | * housekeeping for the gadget function we're implementing.  Most of | 
|  | 675 | * the work is in config-specific setup. | 
|  | 676 | */ | 
|  | 677 | static int gmidi_setup(struct usb_gadget *gadget, | 
|  | 678 | const struct usb_ctrlrequest *ctrl) | 
|  | 679 | { | 
|  | 680 | struct gmidi_device *dev = get_gadget_data(gadget); | 
|  | 681 | struct usb_request *req = dev->req; | 
|  | 682 | int value = -EOPNOTSUPP; | 
|  | 683 | u16 w_index = le16_to_cpu(ctrl->wIndex); | 
|  | 684 | u16 w_value = le16_to_cpu(ctrl->wValue); | 
|  | 685 | u16 w_length = le16_to_cpu(ctrl->wLength); | 
|  | 686 |  | 
|  | 687 | /* usually this stores reply data in the pre-allocated ep0 buffer, | 
|  | 688 | * but config change events will reconfigure hardware. | 
|  | 689 | */ | 
|  | 690 | req->zero = 0; | 
|  | 691 | switch (ctrl->bRequest) { | 
|  | 692 |  | 
|  | 693 | case USB_REQ_GET_DESCRIPTOR: | 
|  | 694 | if (ctrl->bRequestType != USB_DIR_IN) { | 
|  | 695 | goto unknown; | 
|  | 696 | } | 
|  | 697 | switch (w_value >> 8) { | 
|  | 698 |  | 
|  | 699 | case USB_DT_DEVICE: | 
|  | 700 | value = min(w_length, (u16) sizeof(device_desc)); | 
|  | 701 | memcpy(req->buf, &device_desc, value); | 
|  | 702 | break; | 
|  | 703 | case USB_DT_CONFIG: | 
|  | 704 | value = config_buf(gadget, req->buf, | 
|  | 705 | w_value >> 8, | 
|  | 706 | w_value & 0xff); | 
|  | 707 | if (value >= 0) { | 
|  | 708 | value = min(w_length, (u16)value); | 
|  | 709 | } | 
|  | 710 | break; | 
|  | 711 |  | 
|  | 712 | case USB_DT_STRING: | 
|  | 713 | /* wIndex == language code. | 
|  | 714 | * this driver only handles one language, you can | 
|  | 715 | * add string tables for other languages, using | 
|  | 716 | * any UTF-8 characters | 
|  | 717 | */ | 
|  | 718 | value = usb_gadget_get_string(&stringtab, | 
|  | 719 | w_value & 0xff, req->buf); | 
|  | 720 | if (value >= 0) { | 
|  | 721 | value = min(w_length, (u16)value); | 
|  | 722 | } | 
|  | 723 | break; | 
|  | 724 | } | 
|  | 725 | break; | 
|  | 726 |  | 
|  | 727 | /* currently two configs, two speeds */ | 
|  | 728 | case USB_REQ_SET_CONFIGURATION: | 
|  | 729 | if (ctrl->bRequestType != 0) { | 
|  | 730 | goto unknown; | 
|  | 731 | } | 
|  | 732 | if (gadget->a_hnp_support) { | 
|  | 733 | DBG(dev, "HNP available\n"); | 
|  | 734 | } else if (gadget->a_alt_hnp_support) { | 
|  | 735 | DBG(dev, "HNP needs a different root port\n"); | 
|  | 736 | } else { | 
|  | 737 | VDBG(dev, "HNP inactive\n"); | 
|  | 738 | } | 
|  | 739 | spin_lock(&dev->lock); | 
|  | 740 | value = gmidi_set_config(dev, w_value, GFP_ATOMIC); | 
|  | 741 | spin_unlock(&dev->lock); | 
|  | 742 | break; | 
|  | 743 | case USB_REQ_GET_CONFIGURATION: | 
|  | 744 | if (ctrl->bRequestType != USB_DIR_IN) { | 
|  | 745 | goto unknown; | 
|  | 746 | } | 
|  | 747 | *(u8 *)req->buf = dev->config; | 
|  | 748 | value = min(w_length, (u16)1); | 
|  | 749 | break; | 
|  | 750 |  | 
|  | 751 | /* until we add altsetting support, or other interfaces, | 
|  | 752 | * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly) | 
|  | 753 | * and already killed pending endpoint I/O. | 
|  | 754 | */ | 
|  | 755 | case USB_REQ_SET_INTERFACE: | 
|  | 756 | if (ctrl->bRequestType != USB_RECIP_INTERFACE) { | 
|  | 757 | goto unknown; | 
|  | 758 | } | 
|  | 759 | spin_lock(&dev->lock); | 
|  | 760 | if (dev->config && w_index < GMIDI_NUM_INTERFACES | 
|  | 761 | && w_value == 0) | 
|  | 762 | { | 
|  | 763 | u8 config = dev->config; | 
|  | 764 |  | 
|  | 765 | /* resets interface configuration, forgets about | 
|  | 766 | * previous transaction state (queued bufs, etc) | 
|  | 767 | * and re-inits endpoint state (toggle etc) | 
|  | 768 | * no response queued, just zero status == success. | 
|  | 769 | * if we had more than one interface we couldn't | 
|  | 770 | * use this "reset the config" shortcut. | 
|  | 771 | */ | 
|  | 772 | gmidi_reset_config(dev); | 
|  | 773 | gmidi_set_config(dev, config, GFP_ATOMIC); | 
|  | 774 | value = 0; | 
|  | 775 | } | 
|  | 776 | spin_unlock(&dev->lock); | 
|  | 777 | break; | 
|  | 778 | case USB_REQ_GET_INTERFACE: | 
|  | 779 | if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) { | 
|  | 780 | goto unknown; | 
|  | 781 | } | 
|  | 782 | if (!dev->config) { | 
|  | 783 | break; | 
|  | 784 | } | 
|  | 785 | if (w_index >= GMIDI_NUM_INTERFACES) { | 
|  | 786 | value = -EDOM; | 
|  | 787 | break; | 
|  | 788 | } | 
|  | 789 | *(u8 *)req->buf = 0; | 
|  | 790 | value = min(w_length, (u16)1); | 
|  | 791 | break; | 
|  | 792 |  | 
|  | 793 | default: | 
|  | 794 | unknown: | 
|  | 795 | VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", | 
|  | 796 | ctrl->bRequestType, ctrl->bRequest, | 
|  | 797 | w_value, w_index, w_length); | 
|  | 798 | } | 
|  | 799 |  | 
|  | 800 | /* respond with data transfer before status phase? */ | 
|  | 801 | if (value >= 0) { | 
|  | 802 | req->length = value; | 
|  | 803 | req->zero = value < w_length; | 
|  | 804 | value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); | 
|  | 805 | if (value < 0) { | 
|  | 806 | DBG(dev, "ep_queue --> %d\n", value); | 
|  | 807 | req->status = 0; | 
|  | 808 | gmidi_setup_complete(gadget->ep0, req); | 
|  | 809 | } | 
|  | 810 | } | 
|  | 811 |  | 
|  | 812 | /* device either stalls (value < 0) or reports success */ | 
|  | 813 | return value; | 
|  | 814 | } | 
|  | 815 |  | 
|  | 816 | static void gmidi_disconnect(struct usb_gadget *gadget) | 
|  | 817 | { | 
|  | 818 | struct gmidi_device *dev = get_gadget_data(gadget); | 
|  | 819 | unsigned long flags; | 
|  | 820 |  | 
|  | 821 | spin_lock_irqsave(&dev->lock, flags); | 
|  | 822 | gmidi_reset_config(dev); | 
|  | 823 |  | 
|  | 824 | /* a more significant application might have some non-usb | 
|  | 825 | * activities to quiesce here, saving resources like power | 
|  | 826 | * or pushing the notification up a network stack. | 
|  | 827 | */ | 
|  | 828 | spin_unlock_irqrestore(&dev->lock, flags); | 
|  | 829 |  | 
|  | 830 | /* next we may get setup() calls to enumerate new connections; | 
|  | 831 | * or an unbind() during shutdown (including removing module). | 
|  | 832 | */ | 
|  | 833 | } | 
|  | 834 |  | 
|  | 835 | static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget) | 
|  | 836 | { | 
|  | 837 | struct gmidi_device *dev = get_gadget_data(gadget); | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 838 | struct snd_card *card; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 839 |  | 
|  | 840 | DBG(dev, "unbind\n"); | 
|  | 841 |  | 
|  | 842 | card = dev->card; | 
|  | 843 | dev->card = NULL; | 
|  | 844 | if (card) { | 
|  | 845 | snd_card_free(card); | 
|  | 846 | } | 
|  | 847 |  | 
|  | 848 | /* we've already been disconnected ... no i/o is active */ | 
|  | 849 | if (dev->req) { | 
|  | 850 | dev->req->length = USB_BUFSIZ; | 
|  | 851 | free_ep_req(gadget->ep0, dev->req); | 
|  | 852 | } | 
|  | 853 | kfree(dev); | 
|  | 854 | set_gadget_data(gadget, NULL); | 
|  | 855 | } | 
|  | 856 |  | 
|  | 857 | static int gmidi_snd_free(struct snd_device *device) | 
|  | 858 | { | 
|  | 859 | return 0; | 
|  | 860 | } | 
|  | 861 |  | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 862 | static void gmidi_transmit_packet(struct usb_request *req, uint8_t p0, | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 863 | uint8_t p1, uint8_t p2, uint8_t p3) | 
|  | 864 | { | 
|  | 865 | unsigned length = req->length; | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 866 | u8 *buf = (u8 *)req->buf + length; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 867 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 868 | buf[0] = p0; | 
|  | 869 | buf[1] = p1; | 
|  | 870 | buf[2] = p2; | 
|  | 871 | buf[3] = p3; | 
|  | 872 | req->length = length + 4; | 
|  | 873 | } | 
|  | 874 |  | 
|  | 875 | /* | 
|  | 876 | * Converts MIDI commands to USB MIDI packets. | 
|  | 877 | */ | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 878 | static void gmidi_transmit_byte(struct usb_request *req, | 
|  | 879 | struct gmidi_in_port *port, uint8_t b) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 880 | { | 
|  | 881 | uint8_t p0 = port->cable; | 
|  | 882 |  | 
|  | 883 | if (b >= 0xf8) { | 
|  | 884 | gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0); | 
|  | 885 | } else if (b >= 0xf0) { | 
|  | 886 | switch (b) { | 
|  | 887 | case 0xf0: | 
|  | 888 | port->data[0] = b; | 
|  | 889 | port->state = STATE_SYSEX_1; | 
|  | 890 | break; | 
|  | 891 | case 0xf1: | 
|  | 892 | case 0xf3: | 
|  | 893 | port->data[0] = b; | 
|  | 894 | port->state = STATE_1PARAM; | 
|  | 895 | break; | 
|  | 896 | case 0xf2: | 
|  | 897 | port->data[0] = b; | 
|  | 898 | port->state = STATE_2PARAM_1; | 
|  | 899 | break; | 
|  | 900 | case 0xf4: | 
|  | 901 | case 0xf5: | 
|  | 902 | port->state = STATE_UNKNOWN; | 
|  | 903 | break; | 
|  | 904 | case 0xf6: | 
|  | 905 | gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0); | 
|  | 906 | port->state = STATE_UNKNOWN; | 
|  | 907 | break; | 
|  | 908 | case 0xf7: | 
|  | 909 | switch (port->state) { | 
|  | 910 | case STATE_SYSEX_0: | 
|  | 911 | gmidi_transmit_packet(req, | 
|  | 912 | p0 | 0x05, 0xf7, 0, 0); | 
|  | 913 | break; | 
|  | 914 | case STATE_SYSEX_1: | 
|  | 915 | gmidi_transmit_packet(req, | 
|  | 916 | p0 | 0x06, port->data[0], 0xf7, 0); | 
|  | 917 | break; | 
|  | 918 | case STATE_SYSEX_2: | 
|  | 919 | gmidi_transmit_packet(req, | 
|  | 920 | p0 | 0x07, port->data[0], | 
|  | 921 | port->data[1], 0xf7); | 
|  | 922 | break; | 
|  | 923 | } | 
|  | 924 | port->state = STATE_UNKNOWN; | 
|  | 925 | break; | 
|  | 926 | } | 
|  | 927 | } else if (b >= 0x80) { | 
|  | 928 | port->data[0] = b; | 
|  | 929 | if (b >= 0xc0 && b <= 0xdf) | 
|  | 930 | port->state = STATE_1PARAM; | 
|  | 931 | else | 
|  | 932 | port->state = STATE_2PARAM_1; | 
|  | 933 | } else { /* b < 0x80 */ | 
|  | 934 | switch (port->state) { | 
|  | 935 | case STATE_1PARAM: | 
|  | 936 | if (port->data[0] < 0xf0) { | 
|  | 937 | p0 |= port->data[0] >> 4; | 
|  | 938 | } else { | 
|  | 939 | p0 |= 0x02; | 
|  | 940 | port->state = STATE_UNKNOWN; | 
|  | 941 | } | 
|  | 942 | gmidi_transmit_packet(req, p0, port->data[0], b, 0); | 
|  | 943 | break; | 
|  | 944 | case STATE_2PARAM_1: | 
|  | 945 | port->data[1] = b; | 
|  | 946 | port->state = STATE_2PARAM_2; | 
|  | 947 | break; | 
|  | 948 | case STATE_2PARAM_2: | 
|  | 949 | if (port->data[0] < 0xf0) { | 
|  | 950 | p0 |= port->data[0] >> 4; | 
|  | 951 | port->state = STATE_2PARAM_1; | 
|  | 952 | } else { | 
|  | 953 | p0 |= 0x03; | 
|  | 954 | port->state = STATE_UNKNOWN; | 
|  | 955 | } | 
|  | 956 | gmidi_transmit_packet(req, | 
|  | 957 | p0, port->data[0], port->data[1], b); | 
|  | 958 | break; | 
|  | 959 | case STATE_SYSEX_0: | 
|  | 960 | port->data[0] = b; | 
|  | 961 | port->state = STATE_SYSEX_1; | 
|  | 962 | break; | 
|  | 963 | case STATE_SYSEX_1: | 
|  | 964 | port->data[1] = b; | 
|  | 965 | port->state = STATE_SYSEX_2; | 
|  | 966 | break; | 
|  | 967 | case STATE_SYSEX_2: | 
|  | 968 | gmidi_transmit_packet(req, | 
|  | 969 | p0 | 0x04, port->data[0], port->data[1], b); | 
|  | 970 | port->state = STATE_SYSEX_0; | 
|  | 971 | break; | 
|  | 972 | } | 
|  | 973 | } | 
|  | 974 | } | 
|  | 975 |  | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 976 | static void gmidi_transmit(struct gmidi_device *dev, struct usb_request *req) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 977 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 978 | struct usb_ep *ep = dev->in_ep; | 
|  | 979 | struct gmidi_in_port *port = &dev->in_port; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 980 |  | 
|  | 981 | if (!ep) { | 
|  | 982 | return; | 
|  | 983 | } | 
|  | 984 | if (!req) { | 
|  | 985 | req = alloc_ep_req(ep, buflen); | 
|  | 986 | } | 
|  | 987 | if (!req) { | 
|  | 988 | ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n"); | 
|  | 989 | return; | 
|  | 990 | } | 
|  | 991 | req->length = 0; | 
|  | 992 | req->complete = gmidi_complete; | 
|  | 993 |  | 
|  | 994 | if (port->active) { | 
|  | 995 | while (req->length + 3 < buflen) { | 
|  | 996 | uint8_t b; | 
|  | 997 | if (snd_rawmidi_transmit(dev->in_substream, &b, 1) | 
|  | 998 | != 1) | 
|  | 999 | { | 
|  | 1000 | port->active = 0; | 
|  | 1001 | break; | 
|  | 1002 | } | 
|  | 1003 | gmidi_transmit_byte(req, port, b); | 
|  | 1004 | } | 
|  | 1005 | } | 
|  | 1006 | if (req->length > 0) { | 
|  | 1007 | usb_ep_queue(ep, req, GFP_ATOMIC); | 
|  | 1008 | } else { | 
|  | 1009 | free_ep_req(ep, req); | 
|  | 1010 | } | 
|  | 1011 | } | 
|  | 1012 |  | 
|  | 1013 | static void gmidi_in_tasklet(unsigned long data) | 
|  | 1014 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1015 | struct gmidi_device *dev = (struct gmidi_device *)data; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1016 |  | 
|  | 1017 | gmidi_transmit(dev, NULL); | 
|  | 1018 | } | 
|  | 1019 |  | 
|  | 1020 | static int gmidi_in_open(struct snd_rawmidi_substream *substream) | 
|  | 1021 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1022 | struct gmidi_device *dev = substream->rmidi->private_data; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1023 |  | 
|  | 1024 | VDBG(dev, "gmidi_in_open\n"); | 
|  | 1025 | dev->in_substream = substream; | 
|  | 1026 | dev->in_port.state = STATE_UNKNOWN; | 
|  | 1027 | return 0; | 
|  | 1028 | } | 
|  | 1029 |  | 
|  | 1030 | static int gmidi_in_close(struct snd_rawmidi_substream *substream) | 
|  | 1031 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1032 | struct gmidi_device *dev = substream->rmidi->private_data; | 
|  | 1033 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1034 | VDBG(dev, "gmidi_in_close\n"); | 
|  | 1035 | return 0; | 
|  | 1036 | } | 
|  | 1037 |  | 
|  | 1038 | static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) | 
|  | 1039 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1040 | struct gmidi_device *dev = substream->rmidi->private_data; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1041 |  | 
|  | 1042 | VDBG(dev, "gmidi_in_trigger %d\n", up); | 
|  | 1043 | dev->in_port.active = up; | 
|  | 1044 | if (up) { | 
|  | 1045 | tasklet_hi_schedule(&dev->tasklet); | 
|  | 1046 | } | 
|  | 1047 | } | 
|  | 1048 |  | 
|  | 1049 | static int gmidi_out_open(struct snd_rawmidi_substream *substream) | 
|  | 1050 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1051 | struct gmidi_device *dev = substream->rmidi->private_data; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1052 |  | 
|  | 1053 | VDBG(dev, "gmidi_out_open\n"); | 
|  | 1054 | dev->out_substream = substream; | 
|  | 1055 | return 0; | 
|  | 1056 | } | 
|  | 1057 |  | 
|  | 1058 | static int gmidi_out_close(struct snd_rawmidi_substream *substream) | 
|  | 1059 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1060 | struct gmidi_device *dev = substream->rmidi->private_data; | 
|  | 1061 |  | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1062 | VDBG(dev, "gmidi_out_close\n"); | 
|  | 1063 | return 0; | 
|  | 1064 | } | 
|  | 1065 |  | 
|  | 1066 | static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up) | 
|  | 1067 | { | 
| David Brownell | 8c07021 | 2007-08-02 00:01:27 -0700 | [diff] [blame] | 1068 | struct gmidi_device *dev = substream->rmidi->private_data; | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1069 |  | 
|  | 1070 | VDBG(dev, "gmidi_out_trigger %d\n", up); | 
|  | 1071 | if (up) { | 
|  | 1072 | set_bit(substream->number, &dev->out_triggered); | 
|  | 1073 | } else { | 
|  | 1074 | clear_bit(substream->number, &dev->out_triggered); | 
|  | 1075 | } | 
|  | 1076 | } | 
|  | 1077 |  | 
|  | 1078 | static struct snd_rawmidi_ops gmidi_in_ops = { | 
|  | 1079 | .open = gmidi_in_open, | 
|  | 1080 | .close = gmidi_in_close, | 
|  | 1081 | .trigger = gmidi_in_trigger, | 
|  | 1082 | }; | 
|  | 1083 |  | 
|  | 1084 | static struct snd_rawmidi_ops gmidi_out_ops = { | 
|  | 1085 | .open = gmidi_out_open, | 
|  | 1086 | .close = gmidi_out_close, | 
|  | 1087 | .trigger = gmidi_out_trigger | 
|  | 1088 | }; | 
|  | 1089 |  | 
|  | 1090 | /* register as a sound "card" */ | 
|  | 1091 | static int gmidi_register_card(struct gmidi_device *dev) | 
|  | 1092 | { | 
|  | 1093 | struct snd_card *card; | 
|  | 1094 | struct snd_rawmidi *rmidi; | 
|  | 1095 | int err; | 
|  | 1096 | int out_ports = 1; | 
|  | 1097 | int in_ports = 1; | 
|  | 1098 | static struct snd_device_ops ops = { | 
|  | 1099 | .dev_free = gmidi_snd_free, | 
|  | 1100 | }; | 
|  | 1101 |  | 
| Takashi Iwai | 183c6e0 | 2009-01-12 15:19:08 +0100 | [diff] [blame] | 1102 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); | 
|  | 1103 | if (err < 0) { | 
|  | 1104 | ERROR(dev, "snd_card_create failed\n"); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1105 | goto fail; | 
|  | 1106 | } | 
|  | 1107 | dev->card = card; | 
|  | 1108 |  | 
|  | 1109 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops); | 
|  | 1110 | if (err < 0) { | 
|  | 1111 | ERROR(dev, "snd_device_new failed: error %d\n", err); | 
|  | 1112 | goto fail; | 
|  | 1113 | } | 
|  | 1114 |  | 
|  | 1115 | strcpy(card->driver, longname); | 
|  | 1116 | strcpy(card->longname, longname); | 
|  | 1117 | strcpy(card->shortname, shortname); | 
|  | 1118 |  | 
|  | 1119 | /* Set up rawmidi */ | 
|  | 1120 | dev->in_port.dev = dev; | 
|  | 1121 | dev->in_port.active = 0; | 
|  | 1122 | snd_component_add(card, "MIDI"); | 
|  | 1123 | err = snd_rawmidi_new(card, "USB MIDI Gadget", 0, | 
|  | 1124 | out_ports, in_ports, &rmidi); | 
|  | 1125 | if (err < 0) { | 
|  | 1126 | ERROR(dev, "snd_rawmidi_new failed: error %d\n", err); | 
|  | 1127 | goto fail; | 
|  | 1128 | } | 
|  | 1129 | dev->rmidi = rmidi; | 
|  | 1130 | strcpy(rmidi->name, card->shortname); | 
|  | 1131 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | 
|  | 1132 | SNDRV_RAWMIDI_INFO_INPUT | | 
|  | 1133 | SNDRV_RAWMIDI_INFO_DUPLEX; | 
|  | 1134 | rmidi->private_data = dev; | 
|  | 1135 |  | 
|  | 1136 | /* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT. | 
|  | 1137 | It's an upside-down world being a gadget. */ | 
|  | 1138 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); | 
|  | 1139 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); | 
|  | 1140 |  | 
|  | 1141 | snd_card_set_dev(card, &dev->gadget->dev); | 
|  | 1142 |  | 
|  | 1143 | /* register it - we're ready to go */ | 
|  | 1144 | err = snd_card_register(card); | 
|  | 1145 | if (err < 0) { | 
|  | 1146 | ERROR(dev, "snd_card_register failed\n"); | 
|  | 1147 | goto fail; | 
|  | 1148 | } | 
|  | 1149 |  | 
|  | 1150 | VDBG(dev, "gmidi_register_card finished ok\n"); | 
|  | 1151 | return 0; | 
|  | 1152 |  | 
|  | 1153 | fail: | 
|  | 1154 | if (dev->card) { | 
|  | 1155 | snd_card_free(dev->card); | 
|  | 1156 | dev->card = NULL; | 
|  | 1157 | } | 
|  | 1158 | return err; | 
|  | 1159 | } | 
|  | 1160 |  | 
|  | 1161 | /* | 
|  | 1162 | * Creates an output endpoint, and initializes output ports. | 
|  | 1163 | */ | 
| David Brownell | 0e530b4 | 2008-04-05 14:17:14 -0700 | [diff] [blame] | 1164 | static int __init gmidi_bind(struct usb_gadget *gadget) | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1165 | { | 
|  | 1166 | struct gmidi_device *dev; | 
|  | 1167 | struct usb_ep *in_ep, *out_ep; | 
|  | 1168 | int gcnum, err = 0; | 
|  | 1169 |  | 
|  | 1170 | /* support optional vendor/distro customization */ | 
|  | 1171 | if (idVendor) { | 
|  | 1172 | if (!idProduct) { | 
| David Brownell | 0027492 | 2007-11-19 12:58:36 -0800 | [diff] [blame] | 1173 | pr_err("idVendor needs idProduct!\n"); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1174 | return -ENODEV; | 
|  | 1175 | } | 
|  | 1176 | device_desc.idVendor = cpu_to_le16(idVendor); | 
|  | 1177 | device_desc.idProduct = cpu_to_le16(idProduct); | 
|  | 1178 | if (bcdDevice) { | 
|  | 1179 | device_desc.bcdDevice = cpu_to_le16(bcdDevice); | 
|  | 1180 | } | 
|  | 1181 | } | 
|  | 1182 | if (iManufacturer) { | 
|  | 1183 | strlcpy(manufacturer, iManufacturer, sizeof(manufacturer)); | 
|  | 1184 | } else { | 
|  | 1185 | snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", | 
| Serge E. Hallyn | 96b644b | 2006-10-02 02:18:13 -0700 | [diff] [blame] | 1186 | init_utsname()->sysname, init_utsname()->release, | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1187 | gadget->name); | 
|  | 1188 | } | 
|  | 1189 | if (iProduct) { | 
|  | 1190 | strlcpy(product_desc, iProduct, sizeof(product_desc)); | 
|  | 1191 | } | 
|  | 1192 | if (iSerialNumber) { | 
|  | 1193 | device_desc.iSerialNumber = STRING_SERIAL, | 
|  | 1194 | strlcpy(serial_number, iSerialNumber, sizeof(serial_number)); | 
|  | 1195 | } | 
|  | 1196 |  | 
|  | 1197 | /* Bulk-only drivers like this one SHOULD be able to | 
|  | 1198 | * autoconfigure on any sane usb controller driver, | 
|  | 1199 | * but there may also be important quirks to address. | 
|  | 1200 | */ | 
|  | 1201 | usb_ep_autoconfig_reset(gadget); | 
|  | 1202 | in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc); | 
|  | 1203 | if (!in_ep) { | 
|  | 1204 | autoconf_fail: | 
| David Brownell | 0027492 | 2007-11-19 12:58:36 -0800 | [diff] [blame] | 1205 | pr_err("%s: can't autoconfigure on %s\n", | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1206 | shortname, gadget->name); | 
|  | 1207 | return -ENODEV; | 
|  | 1208 | } | 
|  | 1209 | EP_IN_NAME = in_ep->name; | 
|  | 1210 | in_ep->driver_data = in_ep;	/* claim */ | 
|  | 1211 |  | 
|  | 1212 | out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc); | 
|  | 1213 | if (!out_ep) { | 
|  | 1214 | goto autoconf_fail; | 
|  | 1215 | } | 
|  | 1216 | EP_OUT_NAME = out_ep->name; | 
|  | 1217 | out_ep->driver_data = out_ep;	/* claim */ | 
|  | 1218 |  | 
|  | 1219 | gcnum = usb_gadget_controller_number(gadget); | 
|  | 1220 | if (gcnum >= 0) { | 
|  | 1221 | device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | 
|  | 1222 | } else { | 
|  | 1223 | /* gmidi is so simple (no altsettings) that | 
|  | 1224 | * it SHOULD NOT have problems with bulk-capable hardware. | 
|  | 1225 | * so warn about unrecognized controllers, don't panic. | 
|  | 1226 | */ | 
| David Brownell | 0027492 | 2007-11-19 12:58:36 -0800 | [diff] [blame] | 1227 | pr_warning("%s: controller '%s' not recognized\n", | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1228 | shortname, gadget->name); | 
| Harvey Harrison | 551509d | 2009-02-11 14:11:36 -0800 | [diff] [blame] | 1229 | device_desc.bcdDevice = cpu_to_le16(0x9999); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1230 | } | 
|  | 1231 |  | 
|  | 1232 |  | 
|  | 1233 | /* ok, we made sense of the hardware ... */ | 
| Christoph Lameter | e94b176 | 2006-12-06 20:33:17 -0800 | [diff] [blame] | 1234 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1235 | if (!dev) { | 
|  | 1236 | return -ENOMEM; | 
|  | 1237 | } | 
|  | 1238 | spin_lock_init(&dev->lock); | 
|  | 1239 | dev->gadget = gadget; | 
|  | 1240 | dev->in_ep = in_ep; | 
|  | 1241 | dev->out_ep = out_ep; | 
|  | 1242 | set_gadget_data(gadget, dev); | 
|  | 1243 | tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev); | 
|  | 1244 |  | 
|  | 1245 | /* preallocate control response and buffer */ | 
| David Brownell | 9d8bab5 | 2007-07-01 11:04:54 -0700 | [diff] [blame] | 1246 | dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ); | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1247 | if (!dev->req) { | 
|  | 1248 | err = -ENOMEM; | 
|  | 1249 | goto fail; | 
|  | 1250 | } | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1251 |  | 
|  | 1252 | dev->req->complete = gmidi_setup_complete; | 
|  | 1253 |  | 
|  | 1254 | device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; | 
|  | 1255 |  | 
|  | 1256 | gadget->ep0->driver_data = dev; | 
|  | 1257 |  | 
|  | 1258 | INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); | 
|  | 1259 | INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, | 
|  | 1260 | EP_OUT_NAME, EP_IN_NAME); | 
|  | 1261 |  | 
|  | 1262 | /* register as an ALSA sound card */ | 
|  | 1263 | err = gmidi_register_card(dev); | 
|  | 1264 | if (err < 0) { | 
|  | 1265 | goto fail; | 
|  | 1266 | } | 
|  | 1267 |  | 
|  | 1268 | VDBG(dev, "gmidi_bind finished ok\n"); | 
|  | 1269 | return 0; | 
|  | 1270 |  | 
|  | 1271 | fail: | 
|  | 1272 | gmidi_unbind(gadget); | 
|  | 1273 | return err; | 
|  | 1274 | } | 
|  | 1275 |  | 
|  | 1276 |  | 
|  | 1277 | static void gmidi_suspend(struct usb_gadget *gadget) | 
|  | 1278 | { | 
|  | 1279 | struct gmidi_device *dev = get_gadget_data(gadget); | 
|  | 1280 |  | 
|  | 1281 | if (gadget->speed == USB_SPEED_UNKNOWN) { | 
|  | 1282 | return; | 
|  | 1283 | } | 
|  | 1284 |  | 
|  | 1285 | DBG(dev, "suspend\n"); | 
|  | 1286 | } | 
|  | 1287 |  | 
|  | 1288 | static void gmidi_resume(struct usb_gadget *gadget) | 
|  | 1289 | { | 
|  | 1290 | struct gmidi_device *dev = get_gadget_data(gadget); | 
|  | 1291 |  | 
|  | 1292 | DBG(dev, "resume\n"); | 
|  | 1293 | } | 
|  | 1294 |  | 
|  | 1295 |  | 
|  | 1296 | static struct usb_gadget_driver gmidi_driver = { | 
|  | 1297 | .speed		= USB_SPEED_FULL, | 
|  | 1298 | .function	= (char *)longname, | 
|  | 1299 | .bind		= gmidi_bind, | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 1300 | .unbind		= gmidi_unbind, | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1301 |  | 
|  | 1302 | .setup		= gmidi_setup, | 
|  | 1303 | .disconnect	= gmidi_disconnect, | 
|  | 1304 |  | 
|  | 1305 | .suspend	= gmidi_suspend, | 
|  | 1306 | .resume		= gmidi_resume, | 
|  | 1307 |  | 
| David Brownell | 6bea476 | 2006-12-05 03:15:33 -0800 | [diff] [blame] | 1308 | .driver		= { | 
| Ben Williamson | f2ebf92c | 2006-08-01 11:28:16 +1000 | [diff] [blame] | 1309 | .name		= (char *)shortname, | 
|  | 1310 | .owner		= THIS_MODULE, | 
|  | 1311 | }, | 
|  | 1312 | }; | 
|  | 1313 |  | 
|  | 1314 | static int __init gmidi_init(void) | 
|  | 1315 | { | 
|  | 1316 | return usb_gadget_register_driver(&gmidi_driver); | 
|  | 1317 | } | 
|  | 1318 | module_init(gmidi_init); | 
|  | 1319 |  | 
|  | 1320 | static void __exit gmidi_cleanup(void) | 
|  | 1321 | { | 
|  | 1322 | usb_gadget_unregister_driver(&gmidi_driver); | 
|  | 1323 | } | 
|  | 1324 | module_exit(gmidi_cleanup); | 
|  | 1325 |  |