diff --git a/sys/conf/files b/sys/conf/files index 9660751b428f..aa97dde244cc 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2561,6 +2561,7 @@ dev/usb/template/usb_template_msc.c optional usb_template dev/usb/template/usb_template_mtp.c optional usb_template dev/usb/template/usb_template_phone.c optional usb_template dev/usb/template/usb_template_serialnet.c optional usb_template +dev/usb/template/usb_template_midi.c optional usb_template # # USB video drivers # diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c index 49bd373a9210..140c0b9b3c23 100644 --- a/sys/dev/usb/template/usb_template.c +++ b/sys/dev/usb/template/usb_template.c @@ -1374,6 +1374,9 @@ usb_temp_setup_by_index(struct usb_device *udev, uint16_t index) case USB_TEMP_SERIALNET: err = usb_temp_setup(udev, &usb_template_serialnet); break; + case USB_TEMP_MIDI: + err = usb_temp_setup(udev, &usb_template_midi); + break; default: return (USB_ERR_INVAL); } diff --git a/sys/dev/usb/template/usb_template.h b/sys/dev/usb/template/usb_template.h index 484608d3de69..1b320c689f1b 100644 --- a/sys/dev/usb/template/usb_template.h +++ b/sys/dev/usb/template/usb_template.h @@ -107,6 +107,7 @@ extern const struct usb_temp_device_desc usb_template_msc; extern const struct usb_temp_device_desc usb_template_mtp; extern const struct usb_temp_device_desc usb_template_phone; extern const struct usb_temp_device_desc usb_template_serialnet; +extern const struct usb_temp_device_desc usb_template_midi; usb_error_t usb_temp_setup(struct usb_device *, const struct usb_temp_device_desc *); diff --git a/sys/dev/usb/template/usb_template_midi.c b/sys/dev/usb/template/usb_template_midi.c new file mode 100644 index 000000000000..eca8eb224b70 --- /dev/null +++ b/sys/dev/usb/template/usb_template_midi.c @@ -0,0 +1,240 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2015 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This file contains the USB template for an USB MIDI Device. + */ + +#ifdef USB_GLOBAL_INCLUDE_FILE +#include USB_GLOBAL_INCLUDE_FILE +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#endif /* USB_GLOBAL_INCLUDE_FILE */ + +enum { + INDEX_MIDI_LANG, + INDEX_MIDI_IF, + INDEX_MIDI_PRODUCT, + INDEX_MIDI_MAX, +}; + +#define STRING_MIDI_PRODUCT \ + "M\0I\0D\0I\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" + +#define STRING_MIDI_IF \ + "M\0I\0D\0I\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" + +/* make the real string descriptors */ + +USB_MAKE_STRING_DESC(STRING_MIDI_IF, string_midi_if); +USB_MAKE_STRING_DESC(STRING_MIDI_PRODUCT, string_midi_product); + +/* prototypes */ + +static const uint8_t midi_desc_raw_0[9] = { + 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01 +}; + +static const void *midi_descs_0[] = { + &midi_desc_raw_0, + NULL +}; + +static const struct usb_temp_interface_desc midi_iface_0 = { + .ppEndpoints = NULL, /* no endpoints */ + .ppRawDesc = midi_descs_0, + .bInterfaceClass = 1, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .iInterface = INDEX_MIDI_IF, +}; + +static const struct usb_temp_packet_size midi_mps = { + .mps[USB_SPEED_LOW] = 8, + .mps[USB_SPEED_FULL] = 64, + .mps[USB_SPEED_HIGH] = 512, +}; + +static const uint8_t midi_desc_raw_7[5] = { + 0x05, 0x25, 0x01, 0x01, 0x01 +}; + +static const void *midi_descs_2[] = { + &midi_desc_raw_7, + NULL +}; + +static const struct usb_temp_endpoint_desc midi_bulk_out_ep = { + .ppRawDesc = midi_descs_2, + .pPacketSize = &midi_mps, + .bEndpointAddress = UE_DIR_OUT, + .bmAttributes = UE_BULK, +}; + +static const uint8_t midi_desc_raw_6[5] = { + 0x05, 0x25, 0x01, 0x01, 0x03, +}; + +static const void *midi_descs_3[] = { + &midi_desc_raw_6, + NULL +}; + +static const struct usb_temp_endpoint_desc midi_bulk_in_ep = { + .ppRawDesc = midi_descs_3, + .pPacketSize = &midi_mps, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_BULK, +}; + +static const struct usb_temp_endpoint_desc *midi_iface_1_ep[] = { + &midi_bulk_out_ep, + &midi_bulk_in_ep, + NULL, +}; + +static const uint8_t midi_desc_raw_1[7] = { + 0x07, 0x24, 0x01, 0x00, 0x01, /* wTotalLength: */ 0x41, 0x00 +}; + +static const uint8_t midi_desc_raw_2[6] = { + 0x06, 0x24, 0x02, 0x01, 0x01, 0x00 +}; + +static const uint8_t midi_desc_raw_3[6] = { + 0x06, 0x24, 0x02, 0x02, 0x02, 0x00 +}; + +static const uint8_t midi_desc_raw_4[9] = { + 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00 +}; + +static const uint8_t midi_desc_raw_5[9] = { + 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00 +}; + +static const void *midi_descs_1[] = { + &midi_desc_raw_1, + &midi_desc_raw_2, + &midi_desc_raw_3, + &midi_desc_raw_4, + &midi_desc_raw_5, + NULL +}; + +static const struct usb_temp_interface_desc midi_iface_1 = { + .ppRawDesc = midi_descs_1, + .ppEndpoints = midi_iface_1_ep, + .bInterfaceClass = 0x01, /* Midi */ + .bInterfaceSubClass = 3, /* MIDI streaming */ + .bInterfaceProtocol = 0, + .iInterface = INDEX_MIDI_IF, +}; + +static const struct usb_temp_interface_desc *midi_interfaces[] = { + &midi_iface_0, + &midi_iface_1, + NULL, +}; + +static const struct usb_temp_config_desc midi_config_desc = { + .ppIfaceDesc = midi_interfaces, + .bmAttributes = UC_BUS_POWERED, + .bMaxPower = 25, /* 50 mA */ + .iConfiguration = INDEX_MIDI_PRODUCT, +}; + +static const struct usb_temp_config_desc *midi_configs[] = { + &midi_config_desc, + NULL, +}; + +static usb_temp_get_string_desc_t midi_get_string_desc; + +const struct usb_temp_device_desc usb_template_midi = { + .getStringDesc = &midi_get_string_desc, + .ppConfigDesc = midi_configs, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x00BB, + .bcdDevice = 0x0100, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .iManufacturer = 0, + .iProduct = INDEX_MIDI_PRODUCT, + .iSerialNumber = 0, +}; + +/*------------------------------------------------------------------------* + * midi_get_string_desc + * + * Return values: + * NULL: Failure. No such string. + * Else: Success. Pointer to string descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +midi_get_string_desc(uint16_t lang_id, uint8_t string_index) +{ + static const void *ptr[INDEX_MIDI_MAX] = { + [INDEX_MIDI_LANG] = &usb_string_lang_en, + [INDEX_MIDI_IF] = &string_midi_if, + [INDEX_MIDI_PRODUCT] = &string_midi_product, + }; + + if (string_index == 0) { + return (&usb_string_lang_en); + } + if (lang_id != 0x0409) { + return (NULL); + } + if (string_index < INDEX_MIDI_MAX) { + return (ptr[string_index]); + } + return (NULL); +} diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 539f88118824..683f3e61b858 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -66,6 +66,7 @@ enum { USB_TEMP_MOUSE, /* USB Mouse */ USB_TEMP_PHONE, /* USB Phone */ USB_TEMP_SERIALNET, /* USB CDC Ethernet and Modem */ + USB_TEMP_MIDI, /* USB MIDI */ USB_TEMP_MAX, }; diff --git a/sys/modules/usb/template/Makefile b/sys/modules/usb/template/Makefile index fc1cca93d3fa..4164177e8e22 100644 --- a/sys/modules/usb/template/Makefile +++ b/sys/modules/usb/template/Makefile @@ -40,6 +40,7 @@ SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \ usb_template_msc.c \ usb_template_mtp.c \ usb_template_phone.c \ - usb_template_serialnet.c + usb_template_serialnet.c \ + usb_template_midi.c .include