usb_template_midi.c revision 283879
1283879Shselasky/* $FreeBSD: head/sys/dev/usb/template/usb_template_midi.c 283879 2015-06-01 11:24:34Z hselasky $ */ 2283879Shselasky/*- 3283879Shselasky * Copyright (c) 2015 Hans Petter Selasky. All rights reserved. 4283879Shselasky * 5283879Shselasky * Redistribution and use in source and binary forms, with or without 6283879Shselasky * modification, are permitted provided that the following conditions 7283879Shselasky * are met: 8283879Shselasky * 1. Redistributions of source code must retain the above copyright 9283879Shselasky * notice, this list of conditions and the following disclaimer. 10283879Shselasky * 2. Redistributions in binary form must reproduce the above copyright 11283879Shselasky * notice, this list of conditions and the following disclaimer in the 12283879Shselasky * documentation and/or other materials provided with the distribution. 13283879Shselasky * 14283879Shselasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15283879Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16283879Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17283879Shselasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18283879Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19283879Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20283879Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21283879Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22283879Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23283879Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24283879Shselasky * SUCH DAMAGE. 25283879Shselasky */ 26283879Shselasky 27283879Shselasky/* 28283879Shselasky * This file contains the USB template for an USB MIDI Device. 29283879Shselasky */ 30283879Shselasky 31283879Shselasky#ifdef USB_GLOBAL_INCLUDE_FILE 32283879Shselasky#include USB_GLOBAL_INCLUDE_FILE 33283879Shselasky#else 34283879Shselasky#include <sys/stdint.h> 35283879Shselasky#include <sys/stddef.h> 36283879Shselasky#include <sys/param.h> 37283879Shselasky#include <sys/queue.h> 38283879Shselasky#include <sys/types.h> 39283879Shselasky#include <sys/systm.h> 40283879Shselasky#include <sys/kernel.h> 41283879Shselasky#include <sys/bus.h> 42283879Shselasky#include <sys/module.h> 43283879Shselasky#include <sys/lock.h> 44283879Shselasky#include <sys/mutex.h> 45283879Shselasky#include <sys/condvar.h> 46283879Shselasky#include <sys/sysctl.h> 47283879Shselasky#include <sys/sx.h> 48283879Shselasky#include <sys/unistd.h> 49283879Shselasky#include <sys/callout.h> 50283879Shselasky#include <sys/malloc.h> 51283879Shselasky#include <sys/priv.h> 52283879Shselasky 53283879Shselasky#include <dev/usb/usb.h> 54283879Shselasky#include <dev/usb/usbdi.h> 55283879Shselasky#include <dev/usb/usb_core.h> 56283879Shselasky 57283879Shselasky#include <dev/usb/template/usb_template.h> 58283879Shselasky#endif /* USB_GLOBAL_INCLUDE_FILE */ 59283879Shselasky 60283879Shselaskyenum { 61283879Shselasky INDEX_MIDI_LANG, 62283879Shselasky INDEX_MIDI_IF, 63283879Shselasky INDEX_MIDI_PRODUCT, 64283879Shselasky INDEX_MIDI_MAX, 65283879Shselasky}; 66283879Shselasky 67283879Shselasky#define STRING_MIDI_PRODUCT \ 68283879Shselasky "M\0I\0D\0I\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 69283879Shselasky 70283879Shselasky#define STRING_MIDI_IF \ 71283879Shselasky "M\0I\0D\0I\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 72283879Shselasky 73283879Shselasky/* make the real string descriptors */ 74283879Shselasky 75283879ShselaskyUSB_MAKE_STRING_DESC(STRING_MIDI_IF, string_midi_if); 76283879ShselaskyUSB_MAKE_STRING_DESC(STRING_MIDI_PRODUCT, string_midi_product); 77283879Shselasky 78283879Shselasky/* prototypes */ 79283879Shselasky 80283879Shselaskystatic const uint8_t midi_desc_raw_0[9] = { 81283879Shselasky 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01 82283879Shselasky}; 83283879Shselasky 84283879Shselaskystatic const void *midi_descs_0[] = { 85283879Shselasky &midi_desc_raw_0, 86283879Shselasky NULL 87283879Shselasky}; 88283879Shselasky 89283879Shselaskystatic const struct usb_temp_interface_desc midi_iface_0 = { 90283879Shselasky .ppEndpoints = NULL, /* no endpoints */ 91283879Shselasky .ppRawDesc = midi_descs_0, 92283879Shselasky .bInterfaceClass = 1, 93283879Shselasky .bInterfaceSubClass = 1, 94283879Shselasky .bInterfaceProtocol = 0, 95283879Shselasky .iInterface = INDEX_MIDI_IF, 96283879Shselasky}; 97283879Shselasky 98283879Shselaskystatic const struct usb_temp_packet_size midi_mps = { 99283879Shselasky .mps[USB_SPEED_LOW] = 8, 100283879Shselasky .mps[USB_SPEED_FULL] = 64, 101283879Shselasky .mps[USB_SPEED_HIGH] = 512, 102283879Shselasky}; 103283879Shselasky 104283879Shselaskystatic const uint8_t midi_desc_raw_7[5] = { 105283879Shselasky 0x05, 0x25, 0x01, 0x01, 0x01 106283879Shselasky}; 107283879Shselasky 108283879Shselaskystatic const void *midi_descs_2[] = { 109283879Shselasky &midi_desc_raw_7, 110283879Shselasky NULL 111283879Shselasky}; 112283879Shselasky 113283879Shselaskystatic const struct usb_temp_endpoint_desc midi_bulk_out_ep = { 114283879Shselasky .ppRawDesc = midi_descs_2, 115283879Shselasky .pPacketSize = &midi_mps, 116283879Shselasky .bEndpointAddress = UE_DIR_OUT, 117283879Shselasky .bmAttributes = UE_BULK, 118283879Shselasky}; 119283879Shselasky 120283879Shselaskystatic const uint8_t midi_desc_raw_6[5] = { 121283879Shselasky 0x05, 0x25, 0x01, 0x01, 0x03, 122283879Shselasky}; 123283879Shselasky 124283879Shselaskystatic const void *midi_descs_3[] = { 125283879Shselasky &midi_desc_raw_6, 126283879Shselasky NULL 127283879Shselasky}; 128283879Shselasky 129283879Shselaskystatic const struct usb_temp_endpoint_desc midi_bulk_in_ep = { 130283879Shselasky .ppRawDesc = midi_descs_3, 131283879Shselasky .pPacketSize = &midi_mps, 132283879Shselasky .bEndpointAddress = UE_DIR_IN, 133283879Shselasky .bmAttributes = UE_BULK, 134283879Shselasky}; 135283879Shselasky 136283879Shselaskystatic const struct usb_temp_endpoint_desc *midi_iface_1_ep[] = { 137283879Shselasky &midi_bulk_out_ep, 138283879Shselasky &midi_bulk_in_ep, 139283879Shselasky NULL, 140283879Shselasky}; 141283879Shselasky 142283879Shselaskystatic const uint8_t midi_desc_raw_1[7] = { 143283879Shselasky 0x07, 0x24, 0x01, 0x00, 0x01, /* wTotalLength: */ 0x41, 0x00 144283879Shselasky}; 145283879Shselasky 146283879Shselaskystatic const uint8_t midi_desc_raw_2[6] = { 147283879Shselasky 0x06, 0x24, 0x02, 0x01, 0x01, 0x00 148283879Shselasky}; 149283879Shselasky 150283879Shselaskystatic const uint8_t midi_desc_raw_3[6] = { 151283879Shselasky 0x06, 0x24, 0x02, 0x02, 0x02, 0x00 152283879Shselasky}; 153283879Shselasky 154283879Shselaskystatic const uint8_t midi_desc_raw_4[9] = { 155283879Shselasky 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00 156283879Shselasky}; 157283879Shselasky 158283879Shselaskystatic const uint8_t midi_desc_raw_5[9] = { 159283879Shselasky 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00 160283879Shselasky}; 161283879Shselasky 162283879Shselaskystatic const void *midi_descs_1[] = { 163283879Shselasky &midi_desc_raw_1, 164283879Shselasky &midi_desc_raw_2, 165283879Shselasky &midi_desc_raw_3, 166283879Shselasky &midi_desc_raw_4, 167283879Shselasky &midi_desc_raw_5, 168283879Shselasky NULL 169283879Shselasky}; 170283879Shselasky 171283879Shselaskystatic const struct usb_temp_interface_desc midi_iface_1 = { 172283879Shselasky .ppRawDesc = midi_descs_1, 173283879Shselasky .ppEndpoints = midi_iface_1_ep, 174283879Shselasky .bInterfaceClass = 0x01, /* Midi */ 175283879Shselasky .bInterfaceSubClass = 3, /* MIDI streaming */ 176283879Shselasky .bInterfaceProtocol = 0, 177283879Shselasky .iInterface = INDEX_MIDI_IF, 178283879Shselasky}; 179283879Shselasky 180283879Shselaskystatic const struct usb_temp_interface_desc *midi_interfaces[] = { 181283879Shselasky &midi_iface_0, 182283879Shselasky &midi_iface_1, 183283879Shselasky NULL, 184283879Shselasky}; 185283879Shselasky 186283879Shselaskystatic const struct usb_temp_config_desc midi_config_desc = { 187283879Shselasky .ppIfaceDesc = midi_interfaces, 188283879Shselasky .bmAttributes = UC_BUS_POWERED, 189283879Shselasky .bMaxPower = 25, /* 50 mA */ 190283879Shselasky .iConfiguration = INDEX_MIDI_PRODUCT, 191283879Shselasky}; 192283879Shselasky 193283879Shselaskystatic const struct usb_temp_config_desc *midi_configs[] = { 194283879Shselasky &midi_config_desc, 195283879Shselasky NULL, 196283879Shselasky}; 197283879Shselasky 198283879Shselaskystatic usb_temp_get_string_desc_t midi_get_string_desc; 199283879Shselasky 200283879Shselaskyconst struct usb_temp_device_desc usb_template_midi = { 201283879Shselasky .getStringDesc = &midi_get_string_desc, 202283879Shselasky .ppConfigDesc = midi_configs, 203283879Shselasky .idVendor = USB_TEMPLATE_VENDOR, 204283879Shselasky .idProduct = 0x00BB, 205283879Shselasky .bcdDevice = 0x0100, 206283879Shselasky .bDeviceClass = 0, 207283879Shselasky .bDeviceSubClass = 0, 208283879Shselasky .bDeviceProtocol = 0, 209283879Shselasky .iManufacturer = 0, 210283879Shselasky .iProduct = INDEX_MIDI_PRODUCT, 211283879Shselasky .iSerialNumber = 0, 212283879Shselasky}; 213283879Shselasky 214283879Shselasky/*------------------------------------------------------------------------* 215283879Shselasky * midi_get_string_desc 216283879Shselasky * 217283879Shselasky * Return values: 218283879Shselasky * NULL: Failure. No such string. 219283879Shselasky * Else: Success. Pointer to string descriptor is returned. 220283879Shselasky *------------------------------------------------------------------------*/ 221283879Shselaskystatic const void * 222283879Shselaskymidi_get_string_desc(uint16_t lang_id, uint8_t string_index) 223283879Shselasky{ 224283879Shselasky static const void *ptr[INDEX_MIDI_MAX] = { 225283879Shselasky [INDEX_MIDI_LANG] = &usb_string_lang_en, 226283879Shselasky [INDEX_MIDI_IF] = &string_midi_if, 227283879Shselasky [INDEX_MIDI_PRODUCT] = &string_midi_product, 228283879Shselasky }; 229283879Shselasky 230283879Shselasky if (string_index == 0) { 231283879Shselasky return (&usb_string_lang_en); 232283879Shselasky } 233283879Shselasky if (lang_id != 0x0409) { 234283879Shselasky return (NULL); 235283879Shselasky } 236283879Shselasky if (string_index < INDEX_MIDI_MAX) { 237283879Shselasky return (ptr[string_index]); 238283879Shselasky } 239283879Shselasky return (NULL); 240283879Shselasky} 241