usb_audio_source.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * USB Audio Source Device (ISO-Transfer) class core.
  3. *
  4. * Copyright (c) 2020 Intel Corporation
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. */
  8. #include <kernel.h>
  9. #include <init.h>
  10. #include <string.h>
  11. #include <sys/byteorder.h>
  12. #include <usb/usb_device.h>
  13. #include <usb/usb_common.h>
  14. #include <usb/class/usb_audio.h>
  15. #define LOG_LEVEL CONFIG_SYS_LOG_USB_SOURCE_LEVEL
  16. #include <logging/log.h>
  17. LOG_MODULE_REGISTER(usb_audio_source);
  18. #include "usb_audio_source_desc.h"
  19. #define AUDIO_STREAM_INTER1 1
  20. static usb_audio_start audio_start_cb;
  21. static usb_ep_callback iso_in_ep_cb;
  22. static bool audio_streaming_enabled;
  23. static void usb_audio_isoc_in(u8_t ep, enum usb_dc_ep_cb_status_code cb_status)
  24. {
  25. LOG_DBG("**isoc_in_cb!**\n");
  26. if (iso_in_ep_cb) {
  27. iso_in_ep_cb(ep, cb_status);
  28. }
  29. }
  30. static void usb_audio_status_cb(enum usb_dc_status_code status, u8_t *param)
  31. {
  32. static u8_t alt_setting;
  33. u8_t iface;
  34. switch (status) {
  35. case USB_DC_INTERFACE:
  36. /* iface: the higher byte, alt_setting: the lower byte */
  37. iface = *(u16_t *)param >> 8;
  38. alt_setting = *(u16_t *)param & 0xff;
  39. LOG_DBG("Set_Int: %d, alt_setting: %d\n", iface, alt_setting);
  40. switch (iface) {
  41. case AUDIO_STREAM_INTER1:
  42. if (!alt_setting) {
  43. audio_streaming_enabled = false;
  44. } else {
  45. audio_streaming_enabled = true;
  46. }
  47. if (audio_start_cb) {
  48. audio_start_cb(audio_streaming_enabled);
  49. }
  50. break;
  51. default:
  52. LOG_ERR("Unavailable interface number");
  53. break;
  54. }
  55. break;
  56. case USB_DC_ERROR:
  57. LOG_ERR("USB device error");
  58. break;
  59. case USB_DC_RESET:
  60. audio_streaming_enabled = false;
  61. if (audio_start_cb) {
  62. audio_start_cb(audio_streaming_enabled);
  63. }
  64. LOG_DBG("USB device reset detected");
  65. break;
  66. case USB_DC_CONNECTED:
  67. LOG_DBG("USB device connected");
  68. break;
  69. case USB_DC_CONFIGURED:
  70. LOG_DBG("USB device configured");
  71. break;
  72. case USB_DC_DISCONNECTED:
  73. audio_streaming_enabled = false;
  74. if (audio_start_cb) {
  75. audio_start_cb(audio_streaming_enabled);
  76. }
  77. LOG_DBG("USB device disconnected");
  78. break;
  79. case USB_DC_SUSPEND:
  80. audio_streaming_enabled = false;
  81. if (audio_start_cb) {
  82. audio_start_cb(audio_streaming_enabled);
  83. }
  84. LOG_DBG("USB device suspended");
  85. break;
  86. case USB_DC_RESUME:
  87. LOG_DBG("USB device resumed");
  88. break;
  89. case USB_DC_HIGHSPEED:
  90. LOG_INF("High-Speed mode handshake package");
  91. break;
  92. case USB_DC_SOF:
  93. LOG_DBG("USB device sof inter");
  94. break;
  95. case USB_DC_UNKNOWN:
  96. default:
  97. LOG_DBG("USB unknown state");
  98. break;
  99. }
  100. }
  101. static int usb_audio_class_handle_req(struct usb_setup_packet *setup, s32_t *len,
  102. u8_t **data)
  103. {
  104. LOG_DBG("class request: 0x%x 0x%x %d",
  105. setup->bRequest, setup->bmRequestType, *len);
  106. return -ENOTSUP;
  107. }
  108. static int usb_audio_custom_handle_req(struct usb_setup_packet *setup, s32_t *len,
  109. u8_t **data)
  110. {
  111. LOG_DBG("custom request: 0x%x 0x%x %d",
  112. setup->bRequest, setup->bmRequestType, *len);
  113. return -ENOTSUP;
  114. }
  115. static int usb_audio_vendor_handle_req(struct usb_setup_packet *setup, s32_t *len,
  116. u8_t **data)
  117. {
  118. LOG_DBG("vendor request: 0x%x 0x%x %d",
  119. setup->bRequest, setup->bmRequestType, *len);
  120. return -ENOTSUP;
  121. }
  122. /* USB endpoint configuration */
  123. static const struct usb_ep_cfg_data usb_audio_ep_cfg[] = {
  124. {
  125. .ep_cb = usb_audio_isoc_in,
  126. .ep_addr = CONFIG_USB_AUDIO_SOURCE_IN_EP_ADDR,
  127. },
  128. };
  129. static const struct usb_cfg_data usb_audio_cfg = {
  130. .usb_device_description = NULL,
  131. .cb_usb_status = usb_audio_status_cb,
  132. .interface = {
  133. .class_handler = usb_audio_class_handle_req,
  134. .custom_handler = usb_audio_custom_handle_req,
  135. .vendor_handler = usb_audio_vendor_handle_req,
  136. },
  137. .num_endpoints = ARRAY_SIZE(usb_audio_ep_cfg),
  138. .endpoint = usb_audio_ep_cfg,
  139. };
  140. static int usb_audio_source_fix_dev_sn(void)
  141. {
  142. int ret;
  143. #ifdef CONFIG_NVRAM_CONFIG
  144. int read_len;
  145. u8_t mac_str[CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN];
  146. read_len = nvram_config_get(CONFIG_USB_AUDIO_SOURCE_SN_NVRAM, mac_str, CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN);
  147. if (read_len < 0) {
  148. LOG_DBG("no sn data in nvram: %d", read_len);
  149. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SOURCE_SN, strlen(CONFIG_USB_AUDIO_SOURCE_SN));
  150. if (ret)
  151. return ret;
  152. } else {
  153. ret = usb_device_register_string_descriptor(DEV_SN_DESC, mac_str, read_len);
  154. if (ret)
  155. return ret;
  156. }
  157. #else
  158. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SOURCE_SN, strlen(CONFIG_USB_AUDIO_SOURCE_SN));
  159. if (ret) {
  160. return ret;
  161. }
  162. #endif
  163. return 0;
  164. }
  165. /*
  166. * API: initialize usb audio source device.
  167. */
  168. int usb_audio_source_init(struct device *dev)
  169. {
  170. int ret;
  171. /* register string descriptor */
  172. ret = usb_device_register_string_descriptor(MANUFACTURE_STR_DESC, CONFIG_USB_AUDIO_SOURCE_MANUFACTURER, strlen(CONFIG_USB_AUDIO_SOURCE_MANUFACTURER));
  173. if (ret) {
  174. return ret;
  175. }
  176. ret = usb_device_register_string_descriptor(PRODUCT_STR_DESC, CONFIG_USB_AUDIO_SOURCE_PRODUCT, strlen(CONFIG_USB_AUDIO_SOURCE_PRODUCT));
  177. if (ret) {
  178. return ret;
  179. }
  180. ret = usb_audio_source_fix_dev_sn();
  181. if (ret) {
  182. return ret;
  183. }
  184. /* register device descriptor */
  185. usb_device_register_descriptors(usb_audio_source_fs_descriptor, usb_audio_source_hs_descriptor);
  186. /* initialize the USB driver with the right configuration */
  187. ret = usb_set_config(&usb_audio_cfg);
  188. if (ret < 0) {
  189. LOG_ERR("Failed to config USB");
  190. return ret;
  191. }
  192. /* enable USB driver */
  193. ret = usb_enable(&usb_audio_cfg);
  194. if (ret < 0) {
  195. LOG_ERR("Failed to enable USB");
  196. return ret;
  197. }
  198. return 0;
  199. }
  200. /*
  201. * API: deinitialize usb audio source device.
  202. */
  203. int usb_audio_source_deinit(void)
  204. {
  205. int ret;
  206. ret = usb_disable();
  207. if (ret) {
  208. LOG_ERR("Failed to disable USB");
  209. return ret;
  210. }
  211. usb_deconfig();
  212. return 0;
  213. }
  214. void usb_audio_source_register_start_cb(usb_audio_start cb)
  215. {
  216. audio_start_cb = cb;
  217. }
  218. void usb_audio_source_register_inter_in_ep_cb(usb_ep_callback cb)
  219. {
  220. iso_in_ep_cb = cb;
  221. }
  222. int usb_audio_source_ep_flush(void)
  223. {
  224. return usb_dc_ep_flush(CONFIG_USB_AUDIO_SOURCE_IN_EP_ADDR);
  225. }