PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/dev/usb/template/usb_template_midi.c

https://bitbucket.org/freebsd/freebsd-base
C | 314 lines | 230 code | 41 blank | 43 comment | 5 complexity | e820f22f3105e4fe90e4dab2adcaabae MD5 | raw file
  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. * This file contains the USB template for an USB MIDI Device.
  35. */
  36. #ifdef USB_GLOBAL_INCLUDE_FILE
  37. #include USB_GLOBAL_INCLUDE_FILE
  38. #else
  39. #include <sys/stdint.h>
  40. #include <sys/stddef.h>
  41. #include <sys/param.h>
  42. #include <sys/queue.h>
  43. #include <sys/types.h>
  44. #include <sys/systm.h>
  45. #include <sys/kernel.h>
  46. #include <sys/bus.h>
  47. #include <sys/module.h>
  48. #include <sys/lock.h>
  49. #include <sys/mutex.h>
  50. #include <sys/condvar.h>
  51. #include <sys/sysctl.h>
  52. #include <sys/sx.h>
  53. #include <sys/unistd.h>
  54. #include <sys/callout.h>
  55. #include <sys/malloc.h>
  56. #include <sys/priv.h>
  57. #include <dev/usb/usb.h>
  58. #include <dev/usb/usbdi.h>
  59. #include <dev/usb/usb_core.h>
  60. #include <dev/usb/usb_ioctl.h>
  61. #include <dev/usb/usb_util.h>
  62. #include <dev/usb/template/usb_template.h>
  63. #endif /* USB_GLOBAL_INCLUDE_FILE */
  64. enum {
  65. MIDI_LANG_INDEX,
  66. MIDI_INTERFACE_INDEX,
  67. MIDI_MANUFACTURER_INDEX,
  68. MIDI_PRODUCT_INDEX,
  69. MIDI_SERIAL_NUMBER_INDEX,
  70. MIDI_MAX_INDEX,
  71. };
  72. #define MIDI_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR
  73. #define MIDI_DEFAULT_PRODUCT_ID 0x27de
  74. #define MIDI_DEFAULT_INTERFACE "MIDI interface"
  75. #define MIDI_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER
  76. #define MIDI_DEFAULT_PRODUCT "MIDI Test Device"
  77. #define MIDI_DEFAULT_SERIAL_NUMBER "March 2008"
  78. static struct usb_string_descriptor midi_interface;
  79. static struct usb_string_descriptor midi_manufacturer;
  80. static struct usb_string_descriptor midi_product;
  81. static struct usb_string_descriptor midi_serial_number;
  82. static struct sysctl_ctx_list midi_ctx_list;
  83. /* prototypes */
  84. static const uint8_t midi_desc_raw_0[9] = {
  85. 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01
  86. };
  87. static const void *midi_descs_0[] = {
  88. &midi_desc_raw_0,
  89. NULL
  90. };
  91. static const struct usb_temp_interface_desc midi_iface_0 = {
  92. .ppEndpoints = NULL, /* no endpoints */
  93. .ppRawDesc = midi_descs_0,
  94. .bInterfaceClass = UICLASS_AUDIO,
  95. .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL,
  96. .bInterfaceProtocol = 0,
  97. .iInterface = MIDI_INTERFACE_INDEX,
  98. };
  99. static const struct usb_temp_packet_size midi_mps = {
  100. .mps[USB_SPEED_LOW] = 8,
  101. .mps[USB_SPEED_FULL] = 64,
  102. .mps[USB_SPEED_HIGH] = 512,
  103. };
  104. static const uint8_t midi_desc_raw_7[5] = {
  105. 0x05, 0x25, 0x01, 0x01, 0x01
  106. };
  107. static const void *midi_descs_2[] = {
  108. &midi_desc_raw_7,
  109. NULL
  110. };
  111. static const struct usb_temp_endpoint_desc midi_bulk_out_ep = {
  112. .ppRawDesc = midi_descs_2,
  113. .pPacketSize = &midi_mps,
  114. .bEndpointAddress = UE_DIR_OUT,
  115. .bmAttributes = UE_BULK,
  116. };
  117. static const uint8_t midi_desc_raw_6[5] = {
  118. 0x05, 0x25, 0x01, 0x01, 0x03,
  119. };
  120. static const void *midi_descs_3[] = {
  121. &midi_desc_raw_6,
  122. NULL
  123. };
  124. static const struct usb_temp_endpoint_desc midi_bulk_in_ep = {
  125. .ppRawDesc = midi_descs_3,
  126. .pPacketSize = &midi_mps,
  127. .bEndpointAddress = UE_DIR_IN,
  128. .bmAttributes = UE_BULK,
  129. };
  130. static const struct usb_temp_endpoint_desc *midi_iface_1_ep[] = {
  131. &midi_bulk_out_ep,
  132. &midi_bulk_in_ep,
  133. NULL,
  134. };
  135. static const uint8_t midi_desc_raw_1[7] = {
  136. 0x07, 0x24, 0x01, 0x00, 0x01, /* wTotalLength: */ 0x41, 0x00
  137. };
  138. static const uint8_t midi_desc_raw_2[6] = {
  139. 0x06, 0x24, 0x02, 0x01, 0x01, 0x00
  140. };
  141. static const uint8_t midi_desc_raw_3[6] = {
  142. 0x06, 0x24, 0x02, 0x02, 0x02, 0x00
  143. };
  144. static const uint8_t midi_desc_raw_4[9] = {
  145. 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00
  146. };
  147. static const uint8_t midi_desc_raw_5[9] = {
  148. 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00
  149. };
  150. static const void *midi_descs_1[] = {
  151. &midi_desc_raw_1,
  152. &midi_desc_raw_2,
  153. &midi_desc_raw_3,
  154. &midi_desc_raw_4,
  155. &midi_desc_raw_5,
  156. NULL
  157. };
  158. static const struct usb_temp_interface_desc midi_iface_1 = {
  159. .ppRawDesc = midi_descs_1,
  160. .ppEndpoints = midi_iface_1_ep,
  161. .bInterfaceClass = UICLASS_AUDIO,
  162. .bInterfaceSubClass = UISUBCLASS_MIDISTREAM,
  163. .bInterfaceProtocol = 0,
  164. .iInterface = MIDI_INTERFACE_INDEX,
  165. };
  166. static const struct usb_temp_interface_desc *midi_interfaces[] = {
  167. &midi_iface_0,
  168. &midi_iface_1,
  169. NULL,
  170. };
  171. static const struct usb_temp_config_desc midi_config_desc = {
  172. .ppIfaceDesc = midi_interfaces,
  173. .bmAttributes = 0,
  174. .bMaxPower = 0,
  175. .iConfiguration = MIDI_PRODUCT_INDEX,
  176. };
  177. static const struct usb_temp_config_desc *midi_configs[] = {
  178. &midi_config_desc,
  179. NULL,
  180. };
  181. static usb_temp_get_string_desc_t midi_get_string_desc;
  182. struct usb_temp_device_desc usb_template_midi = {
  183. .getStringDesc = &midi_get_string_desc,
  184. .ppConfigDesc = midi_configs,
  185. .idVendor = MIDI_DEFAULT_VENDOR_ID,
  186. .idProduct = MIDI_DEFAULT_PRODUCT_ID,
  187. .bcdDevice = 0x0100,
  188. .bDeviceClass = 0,
  189. .bDeviceSubClass = 0,
  190. .bDeviceProtocol = 0,
  191. .iManufacturer = MIDI_MANUFACTURER_INDEX,
  192. .iProduct = MIDI_PRODUCT_INDEX,
  193. .iSerialNumber = MIDI_SERIAL_NUMBER_INDEX,
  194. };
  195. /*------------------------------------------------------------------------*
  196. * midi_get_string_desc
  197. *
  198. * Return values:
  199. * NULL: Failure. No such string.
  200. * Else: Success. Pointer to string descriptor is returned.
  201. *------------------------------------------------------------------------*/
  202. static const void *
  203. midi_get_string_desc(uint16_t lang_id, uint8_t string_index)
  204. {
  205. static const void *ptr[MIDI_MAX_INDEX] = {
  206. [MIDI_LANG_INDEX] = &usb_string_lang_en,
  207. [MIDI_INTERFACE_INDEX] = &midi_interface,
  208. [MIDI_MANUFACTURER_INDEX] = &midi_manufacturer,
  209. [MIDI_PRODUCT_INDEX] = &midi_product,
  210. [MIDI_SERIAL_NUMBER_INDEX] = &midi_serial_number,
  211. };
  212. if (string_index == 0) {
  213. return (&usb_string_lang_en);
  214. }
  215. if (lang_id != 0x0409) {
  216. return (NULL);
  217. }
  218. if (string_index < MIDI_MAX_INDEX) {
  219. return (ptr[string_index]);
  220. }
  221. return (NULL);
  222. }
  223. static void
  224. midi_init(void *arg __unused)
  225. {
  226. struct sysctl_oid *parent;
  227. char parent_name[3];
  228. usb_make_str_desc(&midi_interface, sizeof(midi_interface),
  229. MIDI_DEFAULT_INTERFACE);
  230. usb_make_str_desc(&midi_manufacturer, sizeof(midi_manufacturer),
  231. MIDI_DEFAULT_MANUFACTURER);
  232. usb_make_str_desc(&midi_product, sizeof(midi_product),
  233. MIDI_DEFAULT_PRODUCT);
  234. usb_make_str_desc(&midi_serial_number, sizeof(midi_serial_number),
  235. MIDI_DEFAULT_SERIAL_NUMBER);
  236. snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MIDI);
  237. sysctl_ctx_init(&midi_ctx_list);
  238. parent = SYSCTL_ADD_NODE(&midi_ctx_list,
  239. SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
  240. parent_name, CTLFLAG_RW,
  241. 0, "USB MIDI device side template");
  242. SYSCTL_ADD_U16(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  243. "vendor_id", CTLFLAG_RWTUN,
  244. &usb_template_midi.idVendor, 1, "Vendor identifier");
  245. SYSCTL_ADD_U16(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  246. "product_id", CTLFLAG_RWTUN,
  247. &usb_template_midi.idProduct, 1, "Product identifier");
  248. #if 0
  249. SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  250. "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  251. &midi_interface, sizeof(midi_interface), usb_temp_sysctl,
  252. "A", "Interface string");
  253. #endif
  254. SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  255. "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  256. &midi_manufacturer, sizeof(midi_manufacturer), usb_temp_sysctl,
  257. "A", "Manufacturer string");
  258. SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  259. "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  260. &midi_product, sizeof(midi_product), usb_temp_sysctl,
  261. "A", "Product string");
  262. SYSCTL_ADD_PROC(&midi_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  263. "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  264. &midi_serial_number, sizeof(midi_serial_number), usb_temp_sysctl,
  265. "A", "Serial number string");
  266. }
  267. static void
  268. midi_uninit(void *arg __unused)
  269. {
  270. sysctl_ctx_free(&midi_ctx_list);
  271. }
  272. SYSINIT(midi_init, SI_SUB_LOCK, SI_ORDER_FIRST, midi_init, NULL);
  273. SYSUNINIT(midi_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, midi_uninit, NULL);