123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /**
- * @file
- * @brief USB audio device class driver.
- *
- * driver for USB audio sink device.
- */
- #include <kernel.h>
- #include <init.h>
- #include <usb/class/usb_audio.h>
- #include "usb_audio_sink_desc.h"
- #ifdef CONFIG_NVRAM_CONFIG
- #include <drivers/nvram_config.h>
- #endif
- #define LOG_LEVEL CONFIG_SYS_LOG_USB_SINK_LEVEL
- #include <logging/log.h>
- LOG_MODULE_REGISTER(usb_audio_sink);
- #define CUR_DEV_VOLUME_VAL 0x1E00
- static int g_cur_volume = CUR_DEV_VOLUME_VAL;
- static int g_min_volume = MINIMUM_VOLUME;
- static int g_max_volume = MAXIMUM_VOLUME;
- static int g_res_volume = RESOTION_VOLUME;
- static int sync_vol_dat;
- static usb_ep_callback iso_out_ep_cb;
- static usb_audio_volume_sync vol_ctrl_sync_cb;
- static void usb_audio_class_set_mute_vol(struct usb_setup_packet *setup, s32_t *len, u8_t **data)
- {
- LOG_DBG("*data[0]: %d", *data[0]);
- sync_vol_dat = *data[0];
- if (vol_ctrl_sync_cb) {
- vol_ctrl_sync_cb(USOUND_SYNC_HOST_MUTE, LOW_BYTE(setup->wValue), &sync_vol_dat);
- }
- }
- static void usb_audio_class_set_cur_vol(struct usb_setup_packet *setup, s32_t *len, u8_t **data)
- {
- u8_t *temp_data = *data;
- sync_vol_dat = (temp_data[1] << 8) | (temp_data[0]);
- LOG_DBG("host set channel_%d volume: 0x%04x", LOW_BYTE(setup->wValue), sync_vol_dat);
- if (sync_vol_dat == 0x8000) {
- sync_vol_dat = MINIMUM_VOLUME;
- }else if (sync_vol_dat == 0) {
- sync_vol_dat = 65536;
- }
- if (vol_ctrl_sync_cb) {
- vol_ctrl_sync_cb(USOUND_SYNC_HOST_VOL_TYPE, LOW_BYTE(setup->wValue), &sync_vol_dat);
- }
- }
- static int usb_audio_class_handle_req(struct usb_setup_packet *setup, s32_t *len, u8_t **data)
- {
- switch (setup->bmRequestType) {
- case SPECIFIC_REQUEST_IN:
- switch (setup->bRequest) {
- case UAC_GET_CUR:
- if (setup->wIndex == FEATURE_UNIT_INDEX1) {
- if(HIGH_BYTE(setup->wValue) == MUTE_CONTROL){
- *data = (u8_t *)&sync_vol_dat;
- *len = MUTE_LENGTH;
- }else if(HIGH_BYTE(setup->wValue) == VOLUME_CONTROL) {
- LOG_DBG("get_cur_vol_value_of_channel_%d", LOW_BYTE(setup->wValue));
- /* the current value of each channel is the same. */
- *data = (u8_t *) &g_cur_volume;
- *len = VOLUME_LENGTH;
- }
- }
- break;
- case UAC_GET_MIN:
- if (setup->wIndex == FEATURE_UNIT_INDEX1) {
- if (HIGH_BYTE(setup->wValue) == VOLUME_CONTROL) {
- LOG_DBG("get_min_vol_value_of_channel_%d", LOW_BYTE(setup->wValue));
- /* the minimum value of each channel is the same. */
- *data = (u8_t *) &g_min_volume;
- *len = VOLUME_LENGTH;
- }
- }
- break;
- case UAC_GET_MAX:
- if (setup->wIndex == FEATURE_UNIT_INDEX1) {
- if (HIGH_BYTE(setup->wValue) == VOLUME_CONTROL) {
- LOG_DBG("get_max_vol_value_of_channel_%d", LOW_BYTE(setup->wValue));
- /* the maximum value of each channel is the same. */
- *data = (u8_t *) &g_max_volume;
- *len = VOLUME_LENGTH;
- }
- }
- break;
- case UAC_GET_RES:
- if (setup->wIndex == FEATURE_UNIT_INDEX1) {
- if (HIGH_BYTE(setup->wValue) == VOLUME_CONTROL) {
- LOG_DBG("get_resolution_value_of_channel_%d", LOW_BYTE(setup->wValue));
- /* the resolution value of each channel is the same. */
- *data = (u8_t *) &g_res_volume;
- *len = VOLUME_LENGTH;
- }
- }
- break;
- }
- break;
- case SPECIFIC_REQUEST_OUT:
- switch (setup->bRequest) {
- case UAC_SET_CUR:
- if (setup->wIndex == FEATURE_UNIT_INDEX1) {
- if (HIGH_BYTE(setup->wValue) == MUTE_CONTROL) {
- usb_audio_class_set_mute_vol(setup, NULL, data);
- } else if (HIGH_BYTE(setup->wValue) == VOLUME_CONTROL) {
- usb_audio_class_set_cur_vol(setup, NULL, data);
- }
- }
- break;
- }
- break;
- }
- return 0;
- }
- static int usb_audio_custom_handle_req(struct usb_setup_packet *setup, s32_t *len, u8_t **data)
- {
- LOG_DBG("custom request: 0x%x 0x%x %d",
- setup->bRequest, setup->bmRequestType, *len);
- return -ENOTSUP;
- }
- static int usb_audio_vendor_handle_req(struct usb_setup_packet *setup, s32_t *len, u8_t **data)
- {
- LOG_DBG("vendor request: 0x%x 0x%x %d",
- setup->bRequest, setup->bmRequestType, *len);
- return -ENOTSUP;
- }
- static void usb_audio_status_cb(enum usb_dc_status_code status, u8_t *param)
- {
- switch (status) {
- case USB_DC_INTERFACE:
- LOG_DBG("usb device set interface");
- break;
- case USB_DC_ERROR:
- LOG_DBG("usb device error");
- break;
- case USB_DC_RESET:
- LOG_DBG("usb device reset detected");
- break;
- case USB_DC_CONNECTED:
- LOG_DBG("usb device connected");
- break;
- case USB_DC_CONFIGURED:
- LOG_DBG("usb device configured");
- break;
- case USB_DC_DISCONNECTED:
- LOG_DBG("usb device disconnected");
- break;
- case USB_DC_SUSPEND:
- LOG_DBG("usb device suspended");
- break;
- case USB_DC_RESUME:
- LOG_DBG("usb device resumed");
- break;
- case USB_DC_UNKNOWN:
- default:
- LOG_DBG("usb unknown state");
- break;
- }
- }
- int usb_audio_sink_ep_flush(void)
- {
- return usb_dc_ep_flush(CONFIG_USB_AUDIO_SINK_OUT_EP_ADDR);
- }
- static void usb_audio_isoc_out(u8_t ep, enum usb_dc_ep_cb_status_code cb_status)
- {
- LOG_DBG("audio_isoc_out");
- if (iso_out_ep_cb) {
- iso_out_ep_cb(ep, cb_status);
- }
- }
- static struct usb_ep_cfg_data usb_audio_ep_cfg[] = {
- {
- .ep_cb = usb_audio_isoc_out,
- .ep_addr = CONFIG_USB_AUDIO_SINK_OUT_EP_ADDR,
- },
- };
- static struct usb_cfg_data usb_audio_config = {
- .usb_device_description = NULL,
- .cb_usb_status = usb_audio_status_cb,
- .interface = {
- .class_handler = usb_audio_class_handle_req,
- .custom_handler = usb_audio_custom_handle_req,
- .vendor_handler = usb_audio_vendor_handle_req,
- },
- .num_endpoints = ARRAY_SIZE(usb_audio_ep_cfg),
- .endpoint = usb_audio_ep_cfg,
- };
- /*
- * API: initialize USB audio sound
- */
- static int usb_audio_sink_fix_dev_sn(void)
- {
- int ret;
- #ifdef CONFIG_NVRAM_CONFIG
- int read_len;
- u8_t mac_str[CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN];
- read_len = nvram_config_get(CONFIG_USB_AUDIO_SINK_SN_NVRAM, mac_str, CONFIG_USB_DEVICE_STRING_DESC_MAX_LEN);
- if (read_len < 0) {
- LOG_DBG("no sn data in nvram: %d", read_len);
- ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SINK_SN, strlen(CONFIG_USB_AUDIO_SINK_SN));
- if (ret)
- return ret;
- } else {
- ret = usb_device_register_string_descriptor(DEV_SN_DESC, mac_str, read_len);
- if (ret)
- return ret;
- }
- #else
- ret = usb_device_register_string_descriptor(DEV_SN_DESC, CONFIG_USB_AUDIO_SINK_SN, strlen(CONFIG_USB_AUDIO_SINK_SN));
- if (ret) {
- return ret;
- }
- #endif
- return 0;
- }
- /*
- * API: initialize USB audio sink
- */
- int usb_audio_sink_init(struct device *dev)
- {
- int ret;
- /* register string descriptor */
- ret = usb_device_register_string_descriptor(MANUFACTURE_STR_DESC, CONFIG_USB_AUDIO_SINK_MANUFACTURER, strlen(CONFIG_USB_AUDIO_SINK_MANUFACTURER));
- if (ret) {
- return ret;
- }
- ret = usb_device_register_string_descriptor(PRODUCT_STR_DESC, CONFIG_USB_AUDIO_SINK_PRODUCT, strlen(CONFIG_USB_AUDIO_SINK_PRODUCT));
- if (ret) {
- return ret;
- }
- ret = usb_audio_sink_fix_dev_sn();
- if (ret) {
- return ret;
- }
- /* register device descriptor */
- usb_device_register_descriptors(usb_audio_sink_fs_descriptor, usb_audio_sink_hs_descriptor);
- /* initialize the usb driver with the right configuration */
- ret = usb_set_config(&usb_audio_config);
- if (ret < 0) {
- LOG_ERR("Failed to config USB");
- return ret;
- }
- /* enable usb driver */
- ret = usb_enable(&usb_audio_config);
- if (ret < 0) {
- LOG_ERR("Failed to enable USB");
- return ret;
- }
- return 0;
- }
- /*
- * API: deinitialize USB audio sink
- */
- int usb_audio_sink_deinit(void)
- {
- int ret;
- ret = usb_disable();
- if (ret) {
- LOG_ERR("Failed to disable USB: %d", ret);
- return ret;
- }
- usb_deconfig();
- return 0;
- }
- int usb_audio_sink_ep_read(u8_t *data, u32_t data_len, u32_t *bytes_ret)
- {
- return usb_read(CONFIG_USB_AUDIO_SINK_OUT_EP_ADDR,
- data, data_len, bytes_ret);
- }
- void usb_audio_sink_register_inter_out_ep_cb(usb_ep_callback cb)
- {
- iso_out_ep_cb = cb;
- }
- void usb_audio_sink_register_volume_sync_cb(usb_audio_volume_sync cb)
- {
- vol_ctrl_sync_cb = cb;
- }
|