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