audio_sourcesink.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * USB Audio Class -- Audio Source Sink driver
  3. *
  4. * Copyright (C) 2020 Actions Corporation.
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. */
  8. /*
  9. * NOTE: Implement the interfaces which support audio sourcesink and
  10. * composite device(HID + UAC), support UAC version 1.0 and works in
  11. * both Full-speed and High-speed modes.
  12. *
  13. * Function:
  14. * # support multi sample rate and multi channels.
  15. * # add buffer and timing statistics.
  16. * # more flexible configuration.
  17. * # support feature unit.
  18. * # support high-speed.
  19. * # support version 2.0.
  20. */
  21. #include <kernel.h>
  22. #include <init.h>
  23. #include <string.h>
  24. #include <sys/byteorder.h>
  25. #include <usb/usb_device.h>
  26. #include <usb/usb_common.h>
  27. #include <usb/class/usb_audio.h>
  28. #include "audio_sourcesink_desc.h"
  29. #define LOG_LEVEL CONFIG_SYS_LOG_USB_SOURCESINK_LEVEL
  30. #include <logging/log.h>
  31. LOG_MODULE_REGISTER(audio_sourcesink);
  32. #define CUR_DEV_VOLUME_VAL 0x1E00
  33. #define GET_SAMPLERATE 0xA2
  34. #define SET_ENDPOINT_CONTROL 0x22
  35. #define SAMPLING_FREQ_CONTROL 0x0100
  36. #define FEATURE_UNIT1_ID 0x09
  37. #define FEATURE_UNIT_INDEX1 0x0901
  38. #define AUDIO_STREAM_INTER2 2
  39. #define AUDIO_STREAM_INTER3 3
  40. static u16_t get_volume_val;
  41. static int ch0_cur_vol_val = CUR_DEV_VOLUME_VAL;
  42. static int ch1_cur_vol_val = CUR_DEV_VOLUME_VAL;
  43. static int ch2_cur_vol_val = CUR_DEV_VOLUME_VAL;
  44. static u32_t g_cur_sample_rate = CONFIG_USB_AUDIO_DEVICE_SINK_SAM_FREQ_DOWNLOAD;
  45. static usb_ep_callback iso_in_ep_cb;
  46. static usb_ep_callback iso_out_ep_cb;
  47. static usb_audio_start audio_start_cb;
  48. static usb_audio_pm audio_pm_cb;
  49. static usb_audio_volume_sync vol_ctrl_sync_cb;
  50. static bool audio_streaming_enabled;
  51. static const struct usb_if_descriptor usb_audio_if = {
  52. .bLength = sizeof(struct usb_if_descriptor),
  53. .bDescriptorType = USB_INTERFACE_DESC,
  54. .bInterfaceNumber = CONFIG_USB_AUDIO_DEVICE_IF_NUM,
  55. .bNumEndpoints = 0,
  56. .bInterfaceClass = USB_CLASS_AUDIO,
  57. .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
  58. };
  59. static void usb_audio_status_cb(enum usb_dc_status_code status, u8_t *param)
  60. {
  61. static u8_t alt_setting, iface;
  62. /* Check the USB status and do needed action if required */
  63. switch (status) {
  64. case USB_DC_INTERFACE:
  65. /* iface: the higher byte, alt_setting: the lower byte */
  66. iface = *(u16_t *)param >> 8;
  67. alt_setting = *(u16_t *)param & 0xff;
  68. LOG_DBG("Set_Int: %d, alt_setting: %d", iface, alt_setting);
  69. switch (iface) {
  70. case AUDIO_STREAM_INTER2:
  71. break;
  72. case AUDIO_STREAM_INTER3:
  73. if (!alt_setting) {
  74. audio_streaming_enabled = false;
  75. } else {
  76. audio_streaming_enabled = true;
  77. }
  78. if (audio_start_cb) {
  79. audio_start_cb(audio_streaming_enabled);
  80. }
  81. break;
  82. default:
  83. LOG_WRN("Unavailable interface number");
  84. break;
  85. }
  86. break;
  87. case USB_DC_ALTSETTING:
  88. /* iface: the higher byte, alt_setting: the lower byte */
  89. iface = *(u16_t *)param >> 8;
  90. *(u16_t *)param = (iface << 8) + alt_setting;
  91. LOG_DBG("Get_Int: %d, alt_setting: %d", iface, alt_setting);
  92. break;
  93. case USB_DC_ERROR:
  94. LOG_DBG("USB device error");
  95. break;
  96. case USB_DC_RESET:
  97. audio_streaming_enabled = false;
  98. if (audio_start_cb) {
  99. audio_start_cb(audio_streaming_enabled);
  100. }
  101. LOG_DBG("USB device reset detected");
  102. break;
  103. case USB_DC_CONNECTED:
  104. LOG_DBG("USB device connected");
  105. break;
  106. case USB_DC_CONFIGURED:
  107. LOG_DBG("USB configuration done");
  108. break;
  109. case USB_DC_DISCONNECTED:
  110. audio_streaming_enabled = false;
  111. if (audio_start_cb) {
  112. audio_start_cb(audio_streaming_enabled);
  113. }
  114. LOG_DBG("USB device disconnected");
  115. break;
  116. case USB_DC_SUSPEND:
  117. audio_streaming_enabled = false;
  118. if (audio_start_cb) {
  119. audio_start_cb(audio_streaming_enabled);
  120. }
  121. if (audio_pm_cb) {
  122. audio_pm_cb(true);
  123. }
  124. LOG_DBG("USB device suspended");
  125. break;
  126. case USB_DC_RESUME:
  127. LOG_DBG("USB device resumed");
  128. if (audio_pm_cb) {
  129. audio_pm_cb(false);
  130. }
  131. break;
  132. case USB_DC_HIGHSPEED:
  133. LOG_DBG("USB device stack work in high-speed mode");
  134. break;
  135. case USB_DC_UNKNOWN:
  136. break;
  137. default:
  138. LOG_DBG("USB unknown state");
  139. break;
  140. }
  141. }
  142. static inline int handle_set_sample_rate(struct usb_setup_packet *setup,
  143. s32_t *len, u8_t *buf)
  144. {
  145. switch (setup->bRequest) {
  146. case UAC_SET_CUR:
  147. case UAC_SET_MIN:
  148. case UAC_SET_MAX:
  149. case UAC_SET_RES:
  150. *len = 3;
  151. LOG_DBG("buf[0]: 0x%02x", buf[0]);
  152. LOG_DBG("buf[1]: 0x%02x", buf[1]);
  153. LOG_DBG("buf[2]: 0x%02x", buf[2]);
  154. g_cur_sample_rate = (buf[2] << 16) | (buf[1] << 8) | buf[0];
  155. LOG_DBG("g_cur_sample_rate:%d ", g_cur_sample_rate);
  156. return 0;
  157. default:
  158. break;
  159. }
  160. return -ENOTSUP;
  161. }
  162. static inline int handle_get_sample_rate(struct usb_setup_packet *setup,
  163. s32_t *len, u8_t *buf)
  164. {
  165. switch (setup->bRequest) {
  166. case UAC_GET_CUR:
  167. case UAC_GET_MIN:
  168. case UAC_GET_MAX:
  169. case UAC_GET_RES:
  170. buf[0] = (u8_t)CONFIG_USB_AUDIO_DEVICE_SINK_SAM_FREQ_DOWNLOAD;
  171. buf[1] = (u8_t)(CONFIG_USB_AUDIO_DEVICE_SINK_SAM_FREQ_DOWNLOAD >> 8);
  172. buf[2] = (u8_t)(CONFIG_USB_AUDIO_DEVICE_SINK_SAM_FREQ_DOWNLOAD >> 16);
  173. *len = 3;
  174. return 0;
  175. default:
  176. break;
  177. }
  178. return -ENOTSUP;
  179. }
  180. int usb_audio_source_inep_flush(void)
  181. {
  182. return usb_dc_ep_flush(CONFIG_USB_AUDIO_DEVICE_SOURCE_IN_EP_ADDR);
  183. }
  184. int usb_audio_sink_outep_flush(void)
  185. {
  186. return usb_dc_ep_flush(CONFIG_USB_AUDIO_DEVICE_SINK_OUT_EP_ADDR);
  187. }
  188. static int usb_audio_class_handle_req(struct usb_setup_packet *psetup,
  189. s32_t *len, u8_t **data)
  190. {
  191. int ret = -ENOTSUP;
  192. u8_t *temp_data = *data;
  193. switch (psetup->bmRequestType) {
  194. case SPECIFIC_REQUEST_OUT:
  195. if (psetup->wIndex == FEATURE_UNIT_INDEX1) {
  196. if (psetup->bRequest == UAC_SET_CUR) {
  197. /* process cmd: set mute and unmute */
  198. if (psetup->wValue == ((MUTE_CONTROL << 8) | MAIN_CHANNEL_NUMBER0)) {
  199. LOG_DBG("mute_ch0:%d %d\n", ch0_cur_vol_val, temp_data[0]);
  200. if (ch0_cur_vol_val != temp_data[0]) {
  201. ch0_cur_vol_val = temp_data[0];
  202. if (vol_ctrl_sync_cb) {
  203. if (ch0_cur_vol_val == 1) {
  204. vol_ctrl_sync_cb(USOUND_SYNC_HOST_MUTE, LOW_BYTE(psetup->wValue), &ch0_cur_vol_val);
  205. } else {
  206. vol_ctrl_sync_cb(USOUND_SYNC_HOST_UNMUTE, LOW_BYTE(psetup->wValue), &ch0_cur_vol_val);
  207. }
  208. }
  209. }
  210. }
  211. /* process cmd: set current volume */
  212. else if (psetup->wValue == ((VOLUME_CONTROL << 8) | MAIN_CHANNEL_NUMBER1)) {
  213. ch1_cur_vol_val = (temp_data[1] << 8) | (temp_data[0]);
  214. LOG_DBG("host set volume1:0x%04x", ch1_cur_vol_val);
  215. if (ch1_cur_vol_val == 0x8000) {
  216. ch1_cur_vol_val = MINIMUM_VOLUME;
  217. }
  218. if (ch1_cur_vol_val == 0) {
  219. ch1_cur_vol_val = 65536;
  220. }
  221. if (vol_ctrl_sync_cb) {
  222. vol_ctrl_sync_cb(USOUND_SYNC_HOST_VOL_TYPE, LOW_BYTE(psetup->wValue), &ch1_cur_vol_val);
  223. }
  224. }
  225. }
  226. }
  227. ret = 0;
  228. break;
  229. case SPECIFIC_REQUEST_IN:
  230. *data = (u8_t *) &get_volume_val;
  231. *len = VOLUME_LENGTH;
  232. if (psetup->wIndex == FEATURE_UNIT_INDEX1) {
  233. *len = VOLUME_LENGTH;
  234. if (psetup->bRequest == UAC_GET_CUR) {
  235. if (psetup->wValue == ((MUTE_CONTROL << 8) | MAIN_CHANNEL_NUMBER0)) {
  236. *data = (u8_t *) &ch0_cur_vol_val;
  237. *len = MUTE_LENGTH;
  238. } else if (psetup->wValue == ((VOLUME_CONTROL << 8) | MAIN_CHANNEL_NUMBER1)) {
  239. LOG_DBG("get_volume1");
  240. *data = (u8_t *) &ch1_cur_vol_val;
  241. } else if (psetup->wValue == ((VOLUME_CONTROL << 8) | MAIN_CHANNEL_NUMBER2)) {
  242. LOG_DBG("get_volume2");
  243. *data = (u8_t *) &ch2_cur_vol_val;
  244. }
  245. } else if (psetup->bRequest == UAC_GET_MIN) {
  246. get_volume_val = MINIMUM_VOLUME;
  247. } else if (psetup->bRequest == UAC_GET_MAX) {
  248. get_volume_val = MAXIMUM_VOLUME;
  249. } else if (psetup->bRequest == UAC_GET_RES) {
  250. get_volume_val = RESOTION_VOLUME;
  251. }
  252. }
  253. ret = 0;
  254. break;
  255. case SET_ENDPOINT_CONTROL:
  256. if (psetup->wValue == SAMPLING_FREQ_CONTROL) {
  257. ret = handle_set_sample_rate(psetup, len, *data);
  258. }
  259. break;
  260. case GET_SAMPLERATE:
  261. if (psetup->wValue == SAMPLING_FREQ_CONTROL) {
  262. ret = handle_get_sample_rate(psetup, len, *data);
  263. }
  264. break;
  265. default:
  266. break;
  267. }
  268. return ret;
  269. }
  270. /*
  271. * NOTICE: In composite device case, this function will never be called,
  272. * the reason is same as class request as above.
  273. */
  274. static int usb_audio_custom_handle_req(struct usb_setup_packet *setup,
  275. s32_t *len, u8_t **data)
  276. {
  277. LOG_DBG("custom request: 0x%x 0x%x %d",
  278. setup->bRequest, setup->bmRequestType, *len);
  279. return -ENOTSUP;
  280. }
  281. static int usb_audio_vendor_handle_req(struct usb_setup_packet *setup,
  282. s32_t *len, u8_t **data)
  283. {
  284. LOG_DBG("vendor request: 0x%x 0x%x %d",
  285. setup->bRequest, setup->bmRequestType, *len);
  286. return -ENOTSUP;
  287. }
  288. static void usb_audio_isoc_in_cb(u8_t ep, enum usb_dc_ep_cb_status_code cb_status)
  289. {
  290. LOG_DBG("**isoc_in_cb!**");
  291. if (iso_in_ep_cb) {
  292. iso_in_ep_cb(ep, cb_status);
  293. }
  294. }
  295. static void usb_audio_isoc_out_cb(u8_t ep, enum usb_dc_ep_cb_status_code cb_status)
  296. {
  297. LOG_DBG("**isoc_out_cb!**");
  298. if (iso_out_ep_cb) {
  299. iso_out_ep_cb(ep, cb_status);
  300. }
  301. }
  302. /* USB endpoint configuration */
  303. static const struct usb_ep_cfg_data usb_audio_ep_cfg[] = {
  304. {
  305. .ep_cb = usb_audio_isoc_out_cb,
  306. .ep_addr = CONFIG_USB_AUDIO_DEVICE_SINK_OUT_EP_ADDR,
  307. },
  308. {
  309. .ep_cb = usb_audio_isoc_in_cb,
  310. .ep_addr = CONFIG_USB_AUDIO_DEVICE_SOURCE_IN_EP_ADDR,
  311. }
  312. };
  313. static const struct usb_cfg_data usb_audio_config = {
  314. .usb_device_description = NULL,
  315. .interface_descriptor = &usb_audio_if,
  316. .cb_usb_status = usb_audio_status_cb,
  317. .interface = {
  318. .class_handler = usb_audio_class_handle_req,
  319. .custom_handler = usb_audio_custom_handle_req,
  320. .vendor_handler = usb_audio_vendor_handle_req,
  321. },
  322. .num_endpoints = ARRAY_SIZE(usb_audio_ep_cfg),
  323. .endpoint = usb_audio_ep_cfg,
  324. };
  325. static int usb_audio_fix_dev_sn(void)
  326. {
  327. int ret;
  328. #ifdef CONFIG_NVRAM_CONFIG
  329. int read_len;
  330. u8_t mac_str[CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN];
  331. read_len = nvram_config_get(CONFIG_USB_AUDIO_SOURCESINK_SN_NVRAM, mac_str, CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN);
  332. if (read_len < 0) {
  333. LOG_DBG("no sn data in nvram: %d", read_len);
  334. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SOURCESINK_SN, strlen(CONFIG_USB_AUDIO_SOURCESINK_SN));
  335. if (ret)
  336. return ret;
  337. } else {
  338. ret = usb_device_register_string_descriptor(DEV_SN_DESC, mac_str, read_len);
  339. if (ret)
  340. return ret;
  341. }
  342. #else
  343. ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SOURCESINK_SN, strlen(CONFIG_USB_AUDIO_SOURCESINK_SN));
  344. if (ret)
  345. return ret;
  346. #endif
  347. return 0;
  348. }
  349. /*
  350. * API: initialize USB audio dev
  351. */
  352. int usb_audio_device_init(void)
  353. {
  354. int ret;
  355. /* Register string descriptor */
  356. ret = usb_device_register_string_descriptor(MANUFACTURE_STR_DESC, CONFIG_USB_AUDIO_SOURCESINK_MANUFACTURER, strlen(CONFIG_USB_AUDIO_SOURCESINK_MANUFACTURER));
  357. if (ret) {
  358. return ret;
  359. }
  360. ret = usb_device_register_string_descriptor(PRODUCT_STR_DESC, CONFIG_USB_AUDIO_SOURCESINK_PRODUCT, strlen(CONFIG_USB_AUDIO_SOURCESINK_PRODUCT));
  361. if (ret) {
  362. return ret;
  363. }
  364. ret = usb_audio_fix_dev_sn();
  365. if (ret) {
  366. return ret;
  367. }
  368. /* Register device descriptors */
  369. usb_device_register_descriptors(usb_audio_sourcesink_fs_desc, usb_audio_sourcesink_fs_desc);
  370. /* Initialize the USB driver with the right configuration */
  371. ret = usb_set_config(&usb_audio_config);
  372. if (ret < 0) {
  373. LOG_ERR("Failed to config USB");
  374. return ret;
  375. }
  376. /* Enable USB driver */
  377. ret = usb_enable(&usb_audio_config);
  378. if (ret < 0) {
  379. LOG_ERR("Failed to enable USB");
  380. return ret;
  381. }
  382. return 0;
  383. }
  384. /*
  385. * API: deinitialize USB audio dev
  386. */
  387. int usb_audio_device_exit(void)
  388. {
  389. int ret;
  390. ret = usb_disable();
  391. if (ret) {
  392. LOG_ERR("Failed to disable USB: %d", ret);
  393. return ret;
  394. }
  395. usb_deconfig();
  396. return 0;
  397. }
  398. /*
  399. * API: Initialize USB audio composite devie
  400. */
  401. int usb_audio_composite_dev_init(void)
  402. {
  403. return usb_decice_composite_set_config(&usb_audio_config);
  404. }
  405. void usb_audio_source_register_pm_cb(usb_audio_pm cb)
  406. {
  407. audio_pm_cb = cb;
  408. }
  409. void usb_audio_device_register_start_cb(usb_audio_start cb)
  410. {
  411. audio_start_cb = cb;
  412. }
  413. void usb_audio_device_register_inter_in_ep_cb(usb_ep_callback cb)
  414. {
  415. iso_in_ep_cb = cb;
  416. }
  417. void usb_audio_device_register_inter_out_ep_cb(usb_ep_callback cb)
  418. {
  419. iso_out_ep_cb = cb;
  420. }
  421. void usb_audio_device_register_volume_sync_cb(usb_audio_volume_sync cb)
  422. {
  423. vol_ctrl_sync_cb = cb;
  424. }
  425. int usb_audio_device_ep_write(const u8_t *data, u32_t data_len, u32_t *bytes_ret)
  426. {
  427. return usb_write(CONFIG_USB_AUDIO_DEVICE_SOURCE_IN_EP_ADDR,
  428. data, data_len, bytes_ret);
  429. }
  430. int usb_audio_device_ep_read(u8_t *data, u32_t data_len, u32_t *bytes_ret)
  431. {
  432. return usb_read(CONFIG_USB_AUDIO_DEVICE_SINK_OUT_EP_ADDR,
  433. data, data_len, bytes_ret);
  434. }