1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2015 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * This file contains the USB template for an USB MIDI Device. 29 */ 30 31 #ifdef USB_GLOBAL_INCLUDE_FILE 32 #include USB_GLOBAL_INCLUDE_FILE 33 #else 34 #include <sys/stdint.h> 35 #include <sys/stddef.h> 36 #include <sys/param.h> 37 #include <sys/queue.h> 38 #include <sys/types.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/bus.h> 42 #include <sys/module.h> 43 #include <sys/lock.h> 44 #include <sys/mutex.h> 45 #include <sys/condvar.h> 46 #include <sys/sysctl.h> 47 #include <sys/sx.h> 48 #include <sys/unistd.h> 49 #include <sys/callout.h> 50 #include <sys/malloc.h> 51 #include <sys/priv.h> 52 53 #include <dev/usb/usb.h> 54 #include <dev/usb/usbdi.h> 55 #include <dev/usb/usb_core.h> 56 57 #include <dev/usb/template/usb_template.h> 58 #endif /* USB_GLOBAL_INCLUDE_FILE */ 59 60 enum { 61 INDEX_MIDI_LANG, 62 INDEX_MIDI_IF, 63 INDEX_MIDI_PRODUCT, 64 INDEX_MIDI_MAX, 65 }; 66 67 #define STRING_MIDI_PRODUCT \ 68 "M\0I\0D\0I\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 69 70 #define STRING_MIDI_IF \ 71 "M\0I\0D\0I\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 72 73 /* make the real string descriptors */ 74 75 USB_MAKE_STRING_DESC(STRING_MIDI_IF, string_midi_if); 76 USB_MAKE_STRING_DESC(STRING_MIDI_PRODUCT, string_midi_product); 77 78 /* prototypes */ 79 80 static const uint8_t midi_desc_raw_0[9] = { 81 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01 82 }; 83 84 static const void *midi_descs_0[] = { 85 &midi_desc_raw_0, 86 NULL 87 }; 88 89 static const struct usb_temp_interface_desc midi_iface_0 = { 90 .ppEndpoints = NULL, /* no endpoints */ 91 .ppRawDesc = midi_descs_0, 92 .bInterfaceClass = 1, 93 .bInterfaceSubClass = 1, 94 .bInterfaceProtocol = 0, 95 .iInterface = INDEX_MIDI_IF, 96 }; 97 98 static const struct usb_temp_packet_size midi_mps = { 99 .mps[USB_SPEED_LOW] = 8, 100 .mps[USB_SPEED_FULL] = 64, 101 .mps[USB_SPEED_HIGH] = 512, 102 }; 103 104 static const uint8_t midi_desc_raw_7[5] = { 105 0x05, 0x25, 0x01, 0x01, 0x01 106 }; 107 108 static const void *midi_descs_2[] = { 109 &midi_desc_raw_7, 110 NULL 111 }; 112 113 static const struct usb_temp_endpoint_desc midi_bulk_out_ep = { 114 .ppRawDesc = midi_descs_2, 115 .pPacketSize = &midi_mps, 116 .bEndpointAddress = UE_DIR_OUT, 117 .bmAttributes = UE_BULK, 118 }; 119 120 static const uint8_t midi_desc_raw_6[5] = { 121 0x05, 0x25, 0x01, 0x01, 0x03, 122 }; 123 124 static const void *midi_descs_3[] = { 125 &midi_desc_raw_6, 126 NULL 127 }; 128 129 static const struct usb_temp_endpoint_desc midi_bulk_in_ep = { 130 .ppRawDesc = midi_descs_3, 131 .pPacketSize = &midi_mps, 132 .bEndpointAddress = UE_DIR_IN, 133 .bmAttributes = UE_BULK, 134 }; 135 136 static const struct usb_temp_endpoint_desc *midi_iface_1_ep[] = { 137 &midi_bulk_out_ep, 138 &midi_bulk_in_ep, 139 NULL, 140 }; 141 142 static const uint8_t midi_desc_raw_1[7] = { 143 0x07, 0x24, 0x01, 0x00, 0x01, /* wTotalLength: */ 0x41, 0x00 144 }; 145 146 static const uint8_t midi_desc_raw_2[6] = { 147 0x06, 0x24, 0x02, 0x01, 0x01, 0x00 148 }; 149 150 static const uint8_t midi_desc_raw_3[6] = { 151 0x06, 0x24, 0x02, 0x02, 0x02, 0x00 152 }; 153 154 static const uint8_t midi_desc_raw_4[9] = { 155 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00 156 }; 157 158 static const uint8_t midi_desc_raw_5[9] = { 159 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00 160 }; 161 162 static const void *midi_descs_1[] = { 163 &midi_desc_raw_1, 164 &midi_desc_raw_2, 165 &midi_desc_raw_3, 166 &midi_desc_raw_4, 167 &midi_desc_raw_5, 168 NULL 169 }; 170 171 static const struct usb_temp_interface_desc midi_iface_1 = { 172 .ppRawDesc = midi_descs_1, 173 .ppEndpoints = midi_iface_1_ep, 174 .bInterfaceClass = 0x01, /* MIDI */ 175 .bInterfaceSubClass = 3, /* MIDI streaming */ 176 .bInterfaceProtocol = 0, 177 .iInterface = INDEX_MIDI_IF, 178 }; 179 180 static const struct usb_temp_interface_desc *midi_interfaces[] = { 181 &midi_iface_0, 182 &midi_iface_1, 183 NULL, 184 }; 185 186 static const struct usb_temp_config_desc midi_config_desc = { 187 .ppIfaceDesc = midi_interfaces, 188 .bmAttributes = UC_BUS_POWERED, 189 .bMaxPower = 25, /* 50 mA */ 190 .iConfiguration = INDEX_MIDI_PRODUCT, 191 }; 192 193 static const struct usb_temp_config_desc *midi_configs[] = { 194 &midi_config_desc, 195 NULL, 196 }; 197 198 static usb_temp_get_string_desc_t midi_get_string_desc; 199 200 const struct usb_temp_device_desc usb_template_midi = { 201 .getStringDesc = &midi_get_string_desc, 202 .ppConfigDesc = midi_configs, 203 .idVendor = USB_TEMPLATE_VENDOR, 204 .idProduct = 0x00BB, 205 .bcdDevice = 0x0100, 206 .bDeviceClass = 0, 207 .bDeviceSubClass = 0, 208 .bDeviceProtocol = 0, 209 .iManufacturer = 0, 210 .iProduct = INDEX_MIDI_PRODUCT, 211 .iSerialNumber = 0, 212 }; 213 214 /*------------------------------------------------------------------------* 215 * midi_get_string_desc 216 * 217 * Return values: 218 * NULL: Failure. No such string. 219 * Else: Success. Pointer to string descriptor is returned. 220 *------------------------------------------------------------------------*/ 221 static const void * 222 midi_get_string_desc(uint16_t lang_id, uint8_t string_index) 223 { 224 static const void *ptr[INDEX_MIDI_MAX] = { 225 [INDEX_MIDI_LANG] = &usb_string_lang_en, 226 [INDEX_MIDI_IF] = &string_midi_if, 227 [INDEX_MIDI_PRODUCT] = &string_midi_product, 228 }; 229 230 if (string_index == 0) { 231 return (&usb_string_lang_en); 232 } 233 if (lang_id != 0x0409) { 234 return (NULL); 235 } 236 if (string_index < INDEX_MIDI_MAX) { 237 return (ptr[string_index]); 238 } 239 return (NULL); 240 } 241