]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/template/usb_template_midi.c
Import DTS files from Linux 5.2
[FreeBSD/FreeBSD.git] / sys / dev / usb / template / usb_template_midi.c
1 /* $FreeBSD$ */
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4  *
5  * Copyright (c) 2015 Hans Petter Selasky
6  * Copyright (c) 2018 The FreeBSD Foundation
7  * All rights reserved.
8  *
9  * Portions of this software were developed by Edward Tomasz Napierala
10  * under sponsorship from the FreeBSD Foundation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * This file contains the USB template for an USB MIDI Device.
36  */
37
38 #ifdef USB_GLOBAL_INCLUDE_FILE
39 #include USB_GLOBAL_INCLUDE_FILE
40 #else
41 #include <sys/stdint.h>
42 #include <sys/stddef.h>
43 #include <sys/param.h>
44 #include <sys/queue.h>
45 #include <sys/types.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/bus.h>
49 #include <sys/module.h>
50 #include <sys/lock.h>
51 #include <sys/mutex.h>
52 #include <sys/condvar.h>
53 #include <sys/sysctl.h>
54 #include <sys/sx.h>
55 #include <sys/unistd.h>
56 #include <sys/callout.h>
57 #include <sys/malloc.h>
58 #include <sys/priv.h>
59
60 #include <dev/usb/usb.h>
61 #include <dev/usb/usbdi.h>
62 #include <dev/usb/usb_core.h>
63 #include <dev/usb/usb_ioctl.h>
64 #include <dev/usb/usb_util.h>
65
66 #include <dev/usb/template/usb_template.h>
67 #endif                                  /* USB_GLOBAL_INCLUDE_FILE */
68
69 enum {
70         MIDI_LANG_INDEX,
71         MIDI_INTERFACE_INDEX,
72         MIDI_MANUFACTURER_INDEX,
73         MIDI_PRODUCT_INDEX,
74         MIDI_SERIAL_NUMBER_INDEX,
75         MIDI_MAX_INDEX,
76 };
77
78 #define MIDI_DEFAULT_VENDOR_ID          USB_TEMPLATE_VENDOR
79 #define MIDI_DEFAULT_PRODUCT_ID         0x27de
80 #define MIDI_DEFAULT_INTERFACE          "MIDI interface"
81 #define MIDI_DEFAULT_MANUFACTURER       USB_TEMPLATE_MANUFACTURER
82 #define MIDI_DEFAULT_PRODUCT            "MIDI Test Device"
83 #define MIDI_DEFAULT_SERIAL_NUMBER      "March 2008"
84
85 static struct usb_string_descriptor     midi_interface;
86 static struct usb_string_descriptor     midi_manufacturer;
87 static struct usb_string_descriptor     midi_product;
88 static struct usb_string_descriptor     midi_serial_number;
89
90 static struct sysctl_ctx_list           midi_ctx_list;
91
92 /* prototypes */
93
94 static const uint8_t midi_desc_raw_0[9] = {
95         0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01
96 };
97
98 static const void *midi_descs_0[] = {
99         &midi_desc_raw_0,
100         NULL
101 };
102
103 static const struct usb_temp_interface_desc midi_iface_0 = {
104         .ppEndpoints = NULL,            /* no endpoints */
105         .ppRawDesc = midi_descs_0,
106         .bInterfaceClass = UICLASS_AUDIO,
107         .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL,
108         .bInterfaceProtocol = 0,
109         .iInterface = MIDI_INTERFACE_INDEX,
110 };
111
112 static const struct usb_temp_packet_size midi_mps = {
113         .mps[USB_SPEED_LOW] = 8,
114         .mps[USB_SPEED_FULL] = 64,
115         .mps[USB_SPEED_HIGH] = 512,
116 };
117
118 static const uint8_t midi_desc_raw_7[5] = {
119         0x05, 0x25, 0x01, 0x01, 0x01
120 };
121
122 static const void *midi_descs_2[] = {
123         &midi_desc_raw_7,
124         NULL
125 };
126
127 static const struct usb_temp_endpoint_desc midi_bulk_out_ep = {
128         .ppRawDesc = midi_descs_2,
129         .pPacketSize = &midi_mps,
130         .bEndpointAddress = UE_DIR_OUT,
131         .bmAttributes = UE_BULK,
132 };
133
134 static const uint8_t midi_desc_raw_6[5] = {
135         0x05, 0x25, 0x01, 0x01, 0x03,
136 };
137
138 static const void *midi_descs_3[] = {
139         &midi_desc_raw_6,
140         NULL
141 };
142
143 static const struct usb_temp_endpoint_desc midi_bulk_in_ep = {
144         .ppRawDesc = midi_descs_3,
145         .pPacketSize = &midi_mps,
146         .bEndpointAddress = UE_DIR_IN,
147         .bmAttributes = UE_BULK,
148 };
149
150 static const struct usb_temp_endpoint_desc *midi_iface_1_ep[] = {
151         &midi_bulk_out_ep,
152         &midi_bulk_in_ep,
153         NULL,
154 };
155
156 static const uint8_t midi_desc_raw_1[7] = {
157         0x07, 0x24, 0x01, 0x00, 0x01, /* wTotalLength: */ 0x41, 0x00
158 };
159
160 static const uint8_t midi_desc_raw_2[6] = {
161         0x06, 0x24, 0x02, 0x01, 0x01, 0x00
162 };
163
164 static const uint8_t midi_desc_raw_3[6] = {
165         0x06, 0x24, 0x02, 0x02, 0x02, 0x00
166 };
167
168 static const uint8_t midi_desc_raw_4[9] = {
169         0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00
170 };
171
172 static const uint8_t midi_desc_raw_5[9] = {
173         0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00
174 };
175
176 static const void *midi_descs_1[] = {
177         &midi_desc_raw_1,
178         &midi_desc_raw_2,
179         &midi_desc_raw_3,
180         &midi_desc_raw_4,
181         &midi_desc_raw_5,
182         NULL
183 };
184
185 static const struct usb_temp_interface_desc midi_iface_1 = {
186         .ppRawDesc = midi_descs_1,
187         .ppEndpoints = midi_iface_1_ep,
188         .bInterfaceClass = UICLASS_AUDIO,
189         .bInterfaceSubClass = UISUBCLASS_MIDISTREAM,
190         .bInterfaceProtocol = 0,
191         .iInterface = MIDI_INTERFACE_INDEX,
192 };
193
194 static const struct usb_temp_interface_desc *midi_interfaces[] = {
195         &midi_iface_0,
196         &midi_iface_1,
197         NULL,
198 };
199
200 static const struct usb_temp_config_desc midi_config_desc = {
201         .ppIfaceDesc = midi_interfaces,
202         .bmAttributes = 0,
203         .bMaxPower = 0,
204         .iConfiguration = MIDI_PRODUCT_INDEX,
205 };
206
207 static const struct usb_temp_config_desc *midi_configs[] = {
208         &midi_config_desc,
209         NULL,
210 };
211
212 static usb_temp_get_string_desc_t midi_get_string_desc;
213
214 struct usb_temp_device_desc usb_template_midi = {
215         .getStringDesc = &midi_get_string_desc,
216         .ppConfigDesc = midi_configs,
217         .idVendor = MIDI_DEFAULT_VENDOR_ID,
218         .idProduct = MIDI_DEFAULT_PRODUCT_ID,
219         .bcdDevice = 0x0100,
220         .bDeviceClass = 0,
221         .bDeviceSubClass = 0,
222         .bDeviceProtocol = 0,
223         .iManufacturer = MIDI_MANUFACTURER_INDEX,
224         .iProduct = MIDI_PRODUCT_INDEX,
225         .iSerialNumber = MIDI_SERIAL_NUMBER_INDEX,
226 };
227
228 /*------------------------------------------------------------------------*
229  *      midi_get_string_desc
230  *
231  * Return values:
232  * NULL: Failure. No such string.
233  * Else: Success. Pointer to string descriptor is returned.
234  *------------------------------------------------------------------------*/
235 static const void *
236 midi_get_string_desc(uint16_t lang_id, uint8_t string_index)
237 {
238         static const void *ptr[MIDI_MAX_INDEX] = {
239                 [MIDI_LANG_INDEX] = &usb_string_lang_en,
240                 [MIDI_INTERFACE_INDEX] = &midi_interface,
241                 [MIDI_MANUFACTURER_INDEX] = &midi_manufacturer,
242                 [MIDI_PRODUCT_INDEX] = &midi_product,
243                 [MIDI_SERIAL_NUMBER_INDEX] = &midi_serial_number,
244         };
245
246         if (string_index == 0) {
247                 return (&usb_string_lang_en);
248         }
249         if (lang_id != 0x0409) {
250                 return (NULL);
251         }
252         if (string_index < MIDI_MAX_INDEX) {
253                 return (ptr[string_index]);
254         }
255         return (NULL);
256 }
257
258 static void
259 midi_init(void *arg __unused)
260 {
261         struct sysctl_oid *parent;
262         char parent_name[3];
263
264         usb_make_str_desc(&midi_interface, sizeof(midi_interface),
265             MIDI_DEFAULT_INTERFACE);
266         usb_make_str_desc(&midi_manufacturer, sizeof(midi_manufacturer),
267             MIDI_DEFAULT_MANUFACTURER);
268         usb_make_str_desc(&midi_product, sizeof(midi_product),
269             MIDI_DEFAULT_PRODUCT);
270         usb_make_str_desc(&midi_serial_number, sizeof(midi_serial_number),
271             MIDI_DEFAULT_SERIAL_NUMBER);
272
273         snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MIDI);
274         sysctl_ctx_init(&midi_ctx_list);
275
276         parent = SYSCTL_ADD_NODE(&midi_ctx_list,
277             SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
278             parent_name, CTLFLAG_RW,
279             0, "USB MIDI device side template");
280         SYSCTL_ADD_U16(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
281             "vendor_id", CTLFLAG_RWTUN,
282             &usb_template_midi.idVendor, 1, "Vendor identifier");
283         SYSCTL_ADD_U16(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
284             "product_id", CTLFLAG_RWTUN,
285             &usb_template_midi.idProduct, 1, "Product identifier");
286 #if 0
287         SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
288             "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
289             &midi_interface, sizeof(midi_interface), usb_temp_sysctl,
290             "A", "Interface string");
291 #endif
292         SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
293             "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
294             &midi_manufacturer, sizeof(midi_manufacturer), usb_temp_sysctl,
295             "A", "Manufacturer string");
296         SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
297             "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
298             &midi_product, sizeof(midi_product), usb_temp_sysctl,
299             "A", "Product string");
300         SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
301             "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
302             &midi_serial_number, sizeof(midi_serial_number), usb_temp_sysctl,
303             "A", "Serial number string");
304 }
305
306 static void
307 midi_uninit(void *arg __unused)
308 {
309
310         sysctl_ctx_free(&midi_ctx_list);
311 }
312
313 SYSINIT(midi_init, SI_SUB_LOCK, SI_ORDER_FIRST, midi_init, NULL);
314 SYSUNINIT(midi_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, midi_uninit, NULL);