#include "include.h" #include "usb_com.h" #include "usb_desc.h" #include "usb_hid.h" #include "usb_vendor.h" #include "usb_audio.h" ude_cb_t ude_cb; u8 cfg_desc_buf[0x100] AT(.usb_buf.device.desc.buf); void ude_state_reset(ude_cb_t *ude) { ude->devaddr = 0; ude->cfgval = 0; } //Get Status static bool do_get_status(uint status) { u8 buf[2]; buf[0] = status; buf[1] = 0; return usb_ep0_start_transfer(buf, 2); } //Get Device Status static bool do_get_device_status(void) { if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } return do_get_status(0); } //Get Interface Status static bool do_get_interface_status(void) { if (0 == ude_cb.cfgval) { //判断是否已配置 return false; } return do_get_status(0); } //Get EndPoint Status static bool do_get_ep_status(spb_wrap_t *spb) { epcb_t *ep; uint req_epnum = BYTE0(spb->index); uint status = 0; if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } if (0 == ude_cb.cfgval && 0 != req_epnum) { return false; } //查询Endpoint的Stall状态 uint temp = BYTE0(spb->index); uint8_t index = temp & 0x7f; uint8_t dir = temp & BIT(7) ? 1:0; ep = usb_ep_get_for_index(index, dir); status = ep->halt; return do_get_status(status); } //Clear Feature static bool do_clear_feature_for_endpoint(spb_wrap_t *spb) { if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } uint req_epnum = BYTE0(spb->index); if (0 == ude_cb.cfgval && 0 != req_epnum) { return false; } if (FT_EP_STALL != spb->val) { return false; } uint temp = BYTE0(spb->index); uint8_t index = temp & 0x7f; uint8_t dir = temp & BIT(7) ? 1:0; epcb_t *ep = usb_ep_get_for_index(index, dir); usb_ep_clear(ep); return true; } //Set Feature static bool do_set_feature_for_endpoint(spb_wrap_t *spb) { printf("-->do_set_feature_for_endpoint\n"); uint req_epnum = BYTE0(spb->index); if (0 == ude_cb.cfgval && 0 != req_epnum) { return false; } if (FT_EP_STALL != spb->val) { return false; } uint temp = BYTE0(spb->index); uint8_t index = temp & 0x7f; uint8_t dir = temp & BIT(7) ? 1:0; epcb_t *ep = usb_ep_get_for_index(index, dir); usb_ep_halt(ep); return true; } static bool do_set_feature_for_device(spb_wrap_t *spb) { printf("-->do_set_feature_for_device\n"); uint req_epnum = BYTE0(spb->index); if (0 == ude_cb.cfgval && 0 != req_epnum) { return false; } if (FT_DEV_REM_WAKEUP != spb->val) { return false; } usb_device_suspend_enable(); return true; } static bool do_clear_feature_for_device(spb_wrap_t *spb) { printf("-->do_clear_feature_for_device\n"); if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } uint req_epnum = BYTE0(spb->index); if (0 == ude_cb.cfgval && 0 != req_epnum) { return false; } if (FT_DEV_REM_WAKEUP != spb->val) { return false; } return true; } //Get Descriptor通用 static bool do_transfer_descriptor(spb_wrap_t *spb, const void *buf, uint len) { uint inlen = spb->len; if (inlen > len) { inlen = len; } return usb_ep0_start_transfer((uint8_t*)buf, inlen); } //Get String Descriptor static bool do_get_string_descriptor(spb_wrap_t *spb) { uint index = BYTE0(spb->val); u8 *buf = NULL; u8 length = 0; switch (index) { case STR_LANGUAGE_ID: buf = usb_get_lang_id_str_descriptor(&length); return do_transfer_descriptor(spb, buf, length); case STR_MANUFACTURER: buf = usb_get_manufacturer_str_descriptor(&length); return do_transfer_descriptor(spb, buf, length); case STR_PRODUCT: buf = usb_get_product_str_descriptor(&length); return do_transfer_descriptor(spb, buf, length); case STR_SERIAL_NUM: buf = usb_get_serial_str_descriptor(&length); return do_transfer_descriptor(spb, buf, length); default: return false; } } //获取配置描述符,并自动裁剪 AT(.usbdev.com) void get_config_descriptor(void) { u16 cfg_desc_len; u8 *desc_ptr = &cfg_desc_buf[0]; u8 *buf = NULL; u8 length = 0; //copy general config descriptor buf = usb_get_cfg_descriptor(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } else { // unexpected case printf("[Error] you must be rewrite 'usb_get_cfg_descriptor' and return valid cfg desc.\n"); return; } #if USB_AUDIO_EN buf = usb_audio_itf_header_desc_get(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } #if USB_SPEAKER_EN buf = usb_audio_itf_speaker_stream_desc_get(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } #endif // USB_SPEAKER_EN #if USB_MIC_EN buf = usb_audio_itf_mic_stream_desc_get(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } #endif // USB_MIC_EN #endif #if USB_HID_EN buf = usb_hid_itf_desc_get(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } #endif // USB_HID_EN #if USB_VENDOR_EN buf = usb_vendor_itf_desc_get(&length); if (length) { memcpy(desc_ptr, buf, length); desc_ptr += length; } #endif cfg_desc_len = (u32)desc_ptr - (u32)cfg_desc_buf; cfg_desc_buf[2] = (u8)cfg_desc_len; //update total size of config descriptor cfg_desc_buf[3] = (u8)(cfg_desc_len >> 8); printf("desc: %d\n", cfg_desc_len); if (cfg_desc_len > sizeof(cfg_desc_buf)) { printf("--->err: cfg_desc_buf overflow!\n"); while(1); } } //Get Descriptor AT(.usbdev.com) static bool do_get_descriptor(spb_wrap_t *spb) { uint desc_type = BYTE1(spb->val); u8 *buf = NULL; u8 length = 0; switch (desc_type) { case DEVICE_DESCRIPTOR: //1: 设备描述符 buf = usb_get_device_descriptor(&length); return do_transfer_descriptor(spb, buf, length); case CONFIGURATION_DESCRIPTOR: //2: 配置描述符 get_config_descriptor(); return do_transfer_descriptor(spb, cfg_desc_buf, ((u16)cfg_desc_buf[3] << 8) | cfg_desc_buf[2]); case STRING_DESCRIPTOR: //3: 字符串描述符 return do_get_string_descriptor(spb); case INTERFACE_DESCRIPTOR: //4: 接口描述符 break; case ENDPOINT_DESCRIPTOR: //5: 端点描述符 break; case HID_DESCRIPTOR: break; case HID_REPORT_DESCRIPTOR: printf("usb_hid_report_desc_get:%x\n",spb->index); #if USB_HID_EN if (spb->index == USB_HID_ITF_INDEX) { buf = usb_hid_report_desc_get(&length); return do_transfer_descriptor(spb, buf, length); } #endif #if USB_VENDOR_EN if (spb->index == USB_VENDOR_ITF_INDEX) { buf = usb_vendor_report_desc_get(&length); return do_transfer_descriptor(spb, buf, length); } #endif default: break; } return false; } //Get Configuration static bool do_get_configuration(void) { if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } return usb_ep0_start_transfer(&ude_cb.cfgval, 1); } //Set Configuration static bool do_set_configuration(spb_wrap_t *spb) { if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } if (spb->val > 1) { return false; } ude_cb.cfgval = spb->val; #if USB_HID_EN ude_hid_setvalid(true); #endif #if USB_VENDOR_EN ude_vendor_setvalid(true); #endif return true; } //Get Interface static bool do_get_interface(spb_wrap_t *spb) { u8 buf[1] = {0}; if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } #if USB_MIC_EN if (USB_AUDIO_STREAM_MIC_ITF_INDEX == (u8)spb->index) { buf[0] = uda_get_isocin_flag(); } #endif #if USB_SPEAKER_EN if (USB_AUDIO_STREAM_SPEAKER_ITF_INDEX == (u8)spb->index) { buf[0] = uda_get_isocout_flag(); } #endif return usb_ep0_start_transfer(buf, 1); } //Set Interface static bool do_set_interface(spb_wrap_t *spb) { if (0 == ude_cb.devaddr) { //判断地址是否设置 return false; } #if USB_MIC_EN if (USB_AUDIO_STREAM_MIC_ITF_INDEX == spb->index) { //每次开启和关闭MIC之前,都会set interface if (spb->val) { //start mic printf("start mic\n"); uda_set_isocin_flag(1); } else { //stop mic printf("stop mic\n"); uda_set_isocin_flag(0); } } #endif #if USB_SPEAKER_EN if (USB_AUDIO_STREAM_SPEAKER_ITF_INDEX == spb->index) { //每次开启和关闭speaker之前,都会set interface if (spb->val) { printf("start speaker\n"); uda_set_isocout_flag(1); } else { printf("stop speaker\n"); uda_set_isocout_flag(0); } } #endif return true; } static bool usb_set_address(spb_wrap_t *spb) { ude_cb.devaddr = BYTE0(spb->val); return true; } //处理标准命令,主机数据方向为in AT(.usbdev.com) static bool do_standard_in(spb_wrap_t *spb) { switch (spb->recipient) { case ST_REQ_DEVICE: switch (spb->req) { case UR_GET_STATUS: //00: GetStatus return do_get_device_status(); case UR_GET_DESCRIPTOR: //06: GetDescriptor return do_get_descriptor(spb); case UR_GET_CONFIGURATION: //08: GetConfiguration return do_get_configuration(); default: break; } break; case ST_REQ_INTERFACE: switch (spb->req) { case UR_GET_STATUS: if (spb->req == UR_GET_STATUS) { return do_get_interface_status(); } break; case UR_GET_INTERFACE: //0a: GetInterface return do_get_interface(spb); case UR_GET_DESCRIPTOR: //06: GetDescriptor return do_get_descriptor(spb); default: break; } break; case ST_REQ_ENDPOINT: switch (spb->req) { case UR_GET_STATUS: if (spb->req == UR_GET_STATUS) { return do_get_ep_status(spb); } break; default: break; } break; default: break; } return false; } //处理类命令,主机数据为向为in AT(.usbdev.com) static bool do_class_in(spb_wrap_t *spb) { switch (spb->recipient) { case ST_REQ_DEVICE: break; case ST_REQ_INTERFACE: switch (spb->req) { #if USB_AUDIO_EN case UA_GET_CUR: case UA_GET_MIN: case UA_GET_MAX: case UA_GET_RES: if (BYTE1(spb->index) == UA_SPEAKER_UNIT_ID) { #if USB_SPEAKER_EN //Speaker Get Feature Unit Control Request if (BYTE1(spb->val) == UA_MUTE_CTL) { //Mute Control printf("do_get_spk_mute\n"); return uda_get_spk_mute(); } else if (BYTE1(spb->val) == UA_VOL_CTL){ //Volume Control printf("do_get_spk_volume\n"); return uda_get_spk_volume(spb->req); } #endif } else if(BYTE1(spb->index) == UA_MIC_UNIT_ID){ #if USB_MIC_EN //MIC Get Feature Unit Control Request if (BYTE1(spb->val) == UA_MUTE_CTL) { //Mute Control printf("do_get_mic_mute\n"); return uda_get_mic_mute(); } else if (BYTE1(spb->val) == UA_VOL_CTL) { //Volume Control printf("do_get_mic_volume\n"); return uda_get_mic_volume(spb->req); } #endif } break; #endif default: break; } break; case ST_REQ_ENDPOINT: break; default: break; } return false; } //处理标准命令,主机数据方向为out AT(.usbdev.com) static bool do_standard_out(spb_wrap_t *spb) { switch (spb->recipient) { case ST_REQ_DEVICE: switch (spb->req) { case UR_SET_ADDRESS: //05: SetAddress return usb_set_address(spb); case UR_SET_CONFIGURATION: //09: SetConfiguration return do_set_configuration(spb); case UR_CLEAR_FEATURE: return do_clear_feature_for_device(spb); case UR_SET_FEATURE: return do_set_feature_for_device(spb); default: break; } break; case ST_REQ_INTERFACE: switch (spb->req) { case UR_SET_INTERFACE: //0b: SetInterface return do_set_interface(spb); default: break; } break; case ST_REQ_ENDPOINT: switch (spb->req) { case UR_CLEAR_FEATURE: return do_clear_feature_for_endpoint(spb); case UR_SET_FEATURE: return do_set_feature_for_endpoint(spb); default: break; } break; default: break; } return false; } static bool do_class_out(spb_wrap_t *spb, uint8_t *data, uint16_t data_len) { if ((spb->reqtype == 0x21) && (spb->req == UA_SET_CUR)) { if (BYTE1(spb->index) == UA_SPEAKER_UNIT_ID) { if (BYTE1(spb->val) == UA_MUTE_CTL) { //Speaker SET MUTE #if USB_SPEAKER_EN uda_set_spk_mute(data[0]); #endif // USB_SPEAKER_EN } else if (BYTE1(spb->val) == UA_VOL_CTL) { //Speaker SET VOLUME #if USB_SPEAKER_EN uda_set_spk_volume(GET_LE16(&data[0])); #endif // USB_SPEAKER_EN } } else if (BYTE1(spb->index) == UA_MIC_UNIT_ID) { if (BYTE1(spb->val) == UA_MUTE_CTL) { //MIC SET MUTE #if USB_MIC_EN uda_set_mic_mute(data[0]); #endif // USB_MIC_EN } else if (BYTE1(spb->val) == UA_VOL_CTL) { //MIC SET VOLUME #if USB_MIC_EN uda_set_mic_volume(GET_LE16(&data[0])); #endif // USB_MIC_EN } } } return true; } AT(.usbdev.com) bool usb_ep0_ctl_callback(spb_wrap_t *spb, uint8_t *data, uint16_t data_len) { //printf("ep0_rx: \n"); //print_r(spb, sizeof(spb_wrap_t)); if (spb->dir == EP_DIR_IN) { if (spb->type == ST_TYPE_STANDARD) { return do_standard_in(spb); //Standard in } else if (spb->type == ST_TYPE_CLASS) { return do_class_in(spb); //Class in } else { return false; } } else { bool res; if (spb->type == ST_TYPE_STANDARD) { res = do_standard_out(spb); //Standard out } else if (spb->type == ST_TYPE_CLASS) { res = do_class_out(spb, data, data_len); //Class out } else { return false; } return res; } return false; }