static void usb_class_audio_send_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] Pointer to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { /* Body */ audio_stream_struct_t* audio_class = (audio_stream_struct_t*)param; usb_status usbstatus; usbstatus = usb_host_release_tr(audio_class->host_handle, (tr_struct_t*)tr_ptr); if (usbstatus != USB_OK) { USB_PRINTF("_usb_host_release_tr failed:%x\n",(unsigned int)usbstatus); } if (audio_class->send_callback) { audio_class->send_callback(NULL, audio_class->send_param, buffer, len, status); } } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_video_cntrl_callback * Returned Value : USB_OK if command has been passed on USB. * Comments : * This is the callback used when HID information is sent or received * *END*--------------------------------------------------------------------*/ static void usb_class_video_cntrl_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] Pointer to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { /* Body */ usb_video_control_struct_t* video_control = (usb_video_control_struct_t*)param; if (usb_host_release_tr(video_control->host_handle, tr_ptr) != USB_OK) { #ifdef _DEBUG USB_PRINTF("_usb_host_release_tr failed\n"); #endif } video_control->in_setup = FALSE; if (video_control->ctrl_callback) { video_control->ctrl_callback(NULL, video_control->ctrl_param, buffer, len, status); } } /* Endbody */
static void usb_class_audio_control_recv_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] void* to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { /* Body */ audio_control_struct_t* audio_class = (audio_control_struct_t*)param; if (usb_host_release_tr(audio_class->host_handle, (tr_struct_t*)tr_ptr) != USB_OK) { USB_PRINTF("_usb_host_release_tr failed\n"); } if (audio_class->interrupt_callback) { audio_class->interrupt_callback(NULL, audio_class->interrupt_callback_param, buffer, len, status); } } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_hub_cntrl_callback * Returned Value : USB_OK if command has been passed on USB. * Comments : * This is the callback used when hub information is sent or received * *END*--------------------------------------------------------------------*/ void usb_class_hub_int_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] Pointer to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { usb_hub_class_struct_t* hub_class = (usb_hub_class_struct_t*)param; //USB_PRINTF("hub int\n"); if (usb_host_release_tr(hub_class->host_handle, tr_ptr) != USB_OK) { USB_PRINTF("_usb_host_release_tr failed\n"); } hub_class->in_interrupt = FALSE; if (hub_class->interrupt_callback) { hub_class->interrupt_callback(NULL, hub_class->interrupt_param, buffer, len, status); } }
usb_status usb_class_audio_send_data ( /* [IN] audio control class interface pointer */ audio_command_t* audio_ptr, /* [IN] buffer pointer */ uint8_t * buffer, /* [IN] data length */ uint32_t buf_size ) { /* Body */ audio_stream_struct_t* audio_class; usb_status status = USBERR_ERROR; //uint16_t request_value; tr_struct_t* tr_ptr; //usb_audio_command_t* p_endpoint_command; if ((audio_ptr == NULL) || (audio_ptr->class_stream_handle == NULL)) { USB_PRINTF("input parameter error\n"); return USBERR_ERROR; } audio_class = (audio_stream_struct_t*)audio_ptr->class_stream_handle; if ((audio_class == NULL) || (buffer == NULL)) { USB_PRINTF("get audio class parameter error\n"); return USBERR_ERROR; } audio_class->send_callback = audio_ptr->callback_fn; audio_class->send_param = audio_ptr->callback_param; if (audio_class->dev_handle == NULL) { USB_PRINTF("get audio class dev handle error\n"); return USBERR_ERROR; } if (usb_host_get_tr(audio_class->host_handle, usb_class_audio_send_callback, audio_class, &tr_ptr) != USB_OK) { USB_PRINTF("error to get tr\n"); return USBERR_ERROR; } tr_ptr->tx_buffer = buffer; tr_ptr->tx_length = buf_size; status = usb_host_send_data(audio_class->host_handle, audio_class->iso_out_pipe, tr_ptr); if (status != USB_OK) { USB_PRINTF("\nError in _usb_host_send_data: %x", (unsigned int)status); usb_host_release_tr(audio_class->host_handle, tr_ptr); return USBERR_ERROR; } return USB_OK; } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_video_control_recv_data * Returned Value : USB_OK if command has been passed on USB. * Comments : * This function is used to recv interrupt data * *END*--------------------------------------------------------------------*/ usb_status usb_class_video_control_recv_data ( /* [IN] Class Interface structure pointer */ video_command_t* com_ptr, /* [IN] The buffer address */ uint8_t * buffer, /* [IN] The buffer address */ uint16_t length ) { usb_video_control_struct_t* video_control_ptr; tr_struct_t* tr_ptr; usb_status status; if ((com_ptr == NULL) || (com_ptr->class_control_handle == NULL)) { return USBERR_ERROR; } video_control_ptr = (usb_video_control_struct_t*)com_ptr->class_control_handle; if ((video_control_ptr == NULL) || (buffer == NULL)) { #ifdef _DEBUG USB_PRINTF("input parameter error\n"); #endif return USBERR_ERROR; } video_control_ptr->recv_callback = com_ptr->callback_fn; video_control_ptr->recv_param = com_ptr->callback_param; if (video_control_ptr->dev_handle == NULL) { return USBERR_ERROR; } if (usb_host_get_tr(video_control_ptr->host_handle, usb_class_video_control_recv_callback, video_control_ptr, &tr_ptr) != USB_OK) { #ifdef _DEBUG USB_PRINTF("error to get tr\n"); #endif return USBERR_ERROR; } tr_ptr->rx_buffer = buffer; tr_ptr->rx_length = length; status = usb_host_recv_data(video_control_ptr->host_handle, video_control_ptr->control_interrupt_in_pipe, tr_ptr); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("\nError in usb_class_video_recv_data: %x", status); #endif usb_host_release_tr(video_control_ptr->host_handle, tr_ptr); return USBERR_ERROR; } return USB_OK; }
usb_status usb_class_cdc_init_ipipe ( /* ACM interface instance */ cdc_class_call_struct_t * acm_instance ) { /* Body */ usb_status status = USBERR_NO_INTERFACE; usb_acm_class_intf_struct_t * if_acm_ptr; tr_struct_t* tr_ptr; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_init_ipipe"); #endif /* Validity checking, always needed when passing data to lower API */ if (usb_class_cdc_intf_validate(acm_instance)) { if_acm_ptr = (usb_acm_class_intf_struct_t *) acm_instance->class_intf_handle; USB_CDC_ACM_lock(); if (if_acm_ptr->interrupt_pipe != NULL) { if (usb_host_get_tr(if_acm_ptr->host_handle, usb_class_cdc_int_acm_callback, if_acm_ptr, &tr_ptr) != USB_OK) { printf("usb_class_cdc_init_ipipe: error to get tr\n"); return USBERR_ERROR; } tr_ptr->rx_buffer = (uint8_t *) &if_acm_ptr->interrupt_buffer; tr_ptr->rx_length = sizeof(if_acm_ptr->interrupt_buffer); status = usb_host_recv_data(if_acm_ptr->host_handle, if_acm_ptr->interrupt_pipe, tr_ptr); if (status != USB_OK) { printf("\nError in usb_class_cdc_init_ipipe: %x", status); usb_host_release_tr(if_acm_ptr->host_handle, tr_ptr); return USBERR_ERROR; } } else{ status = USBERR_OPEN_PIPE_FAILED; } USB_CDC_ACM_unlock(); } #ifdef _HOST_DEBUG_ if (!status) { DEBUG_LOG_TRACE("usb_class_cdc_init_ipipe, SUCCESSFUL"); } else { DEBUG_LOG_TRACE("usb_class_cdc_init_ipipe, FAILED"); } #endif return status; }
static void usb_class_cdc_cntrl_callback ( /* [IN] Unused */ void * tr_ptr, /* [IN] pointer to the class interface instance */ void * param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { /* Body */ usb_data_class_intf_struct_t * if_ptr; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_cntrl_callback"); #endif /* ** There is no need for USB_lock in the callback function, and there is also no ** need to check if the device is still attached (otherwise this callback ** would never have been called! */ /* Get class interface handle, reset IN_SETUP and call callback */ if_ptr = (usb_data_class_intf_struct_t *)param; if (usb_host_release_tr(if_ptr->host_handle, tr_ptr) != USB_OK) { printf("usb_class_cdc_cntrl_callback: _usb_host_release_tr failed\n"); } if (if_ptr->ctrl_callback) { if_ptr->ctrl_callback(tr_ptr, if_ptr->ctrl_callback_param, buffer, len, status); } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_cntrl_callback, SUCCESSFUL"); #endif } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_audio_cntrl_callback * Returned Value : USB_OK if command has been passed on USB. * Comments : * This is the callback used when audio control information is sent or received. * *END*--------------------------------------------------------------------*/ static void usb_class_audio_cntrl_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] void* to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { /* Body */ usb_status usbstatus; audio_control_struct_t* audio_class = (audio_control_struct_t*)param; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_audio_cntrl_callback"); #endif usbstatus = usb_host_release_tr(audio_class->host_handle, (tr_struct_t*)tr_ptr); if (usbstatus != USB_OK) { USB_PRINTF("_usb_host_release_tr failed status:%d \r\n", (unsigned int)usbstatus); } audio_class->in_setup = FALSE; if (audio_class->ctrl_callback) { audio_class->ctrl_callback(NULL, audio_class->ctrl_param, buffer, len, status); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_audio_cntrl_callback, SUCCESSFUL"); #endif } /* Endbody */
void usb_class_hub_cntrl_callback ( /* [IN] Unused */ void* tr_ptr, /* [IN] Pointer to the class interface instance */ void* param, /* [IN] Data buffer */ uint8_t * buffer, /* [IN] Length of buffer */ uint32_t len, /* [IN] Error code (if any) */ usb_status status ) { usb_hub_class_struct_t* hub_class = (usb_hub_class_struct_t*)param; //USB_PRINTF("ctrl c\n"); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_hub_cntrl_callback"); #endif if (usb_host_release_tr(hub_class->host_handle, tr_ptr) != USB_OK) { USB_PRINTF("_usb_host_release_tr failed\n"); } hub_class->in_setup = FALSE; if (hub_class->ctrl_callback) { hub_class->ctrl_callback(NULL, hub_class->ctrl_param, buffer, len, status); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_hub_cntrl_callback, SUCCESSFUL"); #endif }
static void usb_class_cdc_int_acm_callback ( /* [IN] pointer to pipe */ void * tr_ptr, /* [IN] user-defined parameter */ void * param, /* [IN] buffer address */ uint8_t * buffer, /* [IN] length of data transferred */ uint32_t len, /* [IN] status, hopefully USB_OK or USB_DONE */ uint32_t status ) { /* Body */ //cdc_class_call_struct_t * acm_parser; tr_struct_t* tr_int_ptr; usb_acm_class_intf_struct_t * if_acm_ptr = (usb_acm_class_intf_struct_t *)param; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_int_acm_callback"); #endif if(USB_OK == status) { if (usb_host_release_tr(if_acm_ptr->host_handle, tr_ptr) != USB_OK) { printf("usb_class_cdc_int_acm_callback: _usb_host_release_tr failed\n"); } } else { /* In case of error, e.g. KHCI_ATOM_TR_TO, need to re-issue tr for interrupt pipe */ USB_CDC_ACM_lock(); if (if_acm_ptr->interrupt_pipe != NULL) { if (usb_host_get_tr(if_acm_ptr->host_handle, usb_class_cdc_int_acm_callback, if_acm_ptr, &tr_int_ptr) != USB_OK) { printf("usb_class_cdc_int_acm_callback: error to get tr\n"); } tr_int_ptr->rx_buffer = (uint8_t *) &if_acm_ptr->interrupt_buffer; tr_int_ptr->rx_length = sizeof(if_acm_ptr->interrupt_buffer); status = usb_host_recv_data(if_acm_ptr->host_handle, if_acm_ptr->interrupt_pipe, tr_int_ptr); if (status != USB_OK) { printf("\nError in usb_class_cdc_int_acm_callback: %x", status); usb_host_release_tr(if_acm_ptr->host_handle, tr_int_ptr); } } else{ status = USBERR_OPEN_PIPE_FAILED; } USB_CDC_ACM_unlock(); } /* we do not use USB_ACM_INT_PIPE_FREE in this version at all */ // _lwevent_set(if_ptr->acm_event, USB_ACM_INT_PIPE_FREE); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_int_acm_callback, SUCCESSFUL"); #endif } /*EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_video_cntrl_common * Returned Value : USB_OK if command has been passed on USB. * Comments : * This function is used to send a control request * *END*--------------------------------------------------------------------*/ static usb_status usb_class_video_cntrl_common ( /* [IN] The communication device common command structure */ video_command_t* com_ptr, /* [IN] Bitmask of the request type */ uint8_t bmrequesttype, /* [IN] Request code */ uint8_t brequest, /* [IN] Value to copy into wvalue field of the REQUEST */ uint16_t wvalue, /* [IN] Value to copy into windex field of the REQUEST */ uint16_t windex, /* [IN] Length of the data associated with REQUEST */ uint16_t wlength, /* [IN] Pointer to data buffer used to send/recv */ uint8_t* data ) { /* Body */ usb_video_control_struct_t* video_control = NULL; //usb_setup_t req; usb_status status = USB_OK; usb_pipe_handle pipe_handle; tr_struct_t* tr_ptr; if ((com_ptr == NULL) || (com_ptr->class_control_handle == NULL)) { return USBERR_ERROR; } video_control = (usb_video_control_struct_t*)com_ptr->class_control_handle; if (video_control->in_setup) { return USBERR_TRANSFER_IN_PROGRESS; } if (video_control->dev_handle == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("_usb_hostdev_cntrl_request, invalid device handle"); #endif return USBERR_DEVICE_NOT_FOUND; } video_control->ctrl_callback = com_ptr->callback_fn; video_control->ctrl_param = com_ptr->callback_param; pipe_handle = usb_host_dev_mng_get_control_pipe(video_control->dev_handle); if (usb_host_get_tr(video_control->host_handle, usb_class_video_cntrl_callback, video_control, &tr_ptr) != USB_OK) { #ifdef _DEBUG USB_PRINTF("error to get tr video\n"); #endif return USBERR_ERROR; } /* Set TR buffer length as required */ if ((REQ_TYPE_IN & bmrequesttype) != 0) { tr_ptr->rx_buffer = data; tr_ptr->rx_length = wlength; } else { tr_ptr->tx_buffer = data; tr_ptr->tx_length = wlength; } tr_ptr->setup_packet.bmrequesttype = bmrequesttype; tr_ptr->setup_packet.brequest = brequest; *(uint16_t*)tr_ptr->setup_packet.wvalue = USB_HOST_TO_LE_SHORT(wvalue); *(uint16_t*)tr_ptr->setup_packet.windex = USB_HOST_TO_LE_SHORT(windex); *(uint16_t*)tr_ptr->setup_packet.wlength = USB_HOST_TO_LE_SHORT(wlength); video_control->in_setup = TRUE; status = usb_host_send_setup(video_control->host_handle, pipe_handle, tr_ptr); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("\nError in usb_class_video_cntrl_common: %x", status); #endif video_control->in_setup = FALSE; usb_host_release_tr(video_control->host_handle, tr_ptr); return USBERR_ERROR; } return status; } /* Endbody */
static usb_status usb_class_cdc_cntrl_common ( /* [IN] The communication device common command structure */ cdc_command_t * com_ptr, /* [IN] The communication device control interface */ usb_acm_class_intf_struct_t * if_ctrl_ptr, /* [IN] Bitmask of the request type */ uint8_t bmrequesttype, /* [IN] Request code */ uint8_t brequest, /* [IN] Value to copy into wvalue field of the REQUEST */ uint16_t wvalue, /* [IN] Length of the data associated with REQUEST */ uint16_t wlength, /* [IN] Pointer to data buffer used to send/recv */ uint8_t * data ) { /* Body */ usb_data_class_intf_struct_t * if_ptr; //usb_setup_t req; usb_status status = USBERR_NO_INTERFACE; usb_pipe_handle pipe_handle; tr_struct_t* tr_ptr; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_cdc_cntrl_common"); #endif if_ptr = (usb_data_class_intf_struct_t *) com_ptr->CLASS_PTR->class_intf_handle; /* Save the higher level callback and ID */ if_ptr->ctrl_callback = com_ptr->CALLBACK_FN; if_ptr->ctrl_callback_param = com_ptr->CALLBACK_PARAM; pipe_handle = (usb_pipe_handle)usb_host_dev_mng_get_control_pipe(if_ptr->dev_handle); if (usb_host_get_tr(if_ptr->host_handle, usb_class_cdc_cntrl_callback, if_ptr, &tr_ptr) != USB_OK) { printf("usb_class_cdc_cntrl_common: error to get tr cdc\n"); return USBERR_ERROR; } /* Set TR buffer length as required */ if ((REQ_TYPE_IN & bmrequesttype) != 0) { tr_ptr->rx_buffer = data; tr_ptr->rx_length = wlength; } else { tr_ptr->tx_buffer = data; tr_ptr->tx_length = wlength; } tr_ptr->setup_packet.bmrequesttype = bmrequesttype; tr_ptr->setup_packet.brequest = brequest; *(uint16_t*)tr_ptr->setup_packet.wvalue = USB_HOST_TO_LE_SHORT(wvalue); *(uint16_t*)tr_ptr->setup_packet.windex = USB_HOST_TO_LE_SHORT(if_ctrl_ptr->intf_num); *(uint16_t*)tr_ptr->setup_packet.wlength = USB_HOST_TO_LE_SHORT(wlength); /* Since this function is general, we must distinguish here interface class to perform ** appropriate action. ** Only ACM devices are supported now. */ switch (((interface_descriptor_t*) if_ctrl_ptr->intf_handle)->bInterfaceSubClass) { case USB_SUBCLASS_COM_DIRECT: break; case USB_SUBCLASS_COM_ABSTRACT: if (USB_OK == (status = usb_host_send_setup(if_ptr->host_handle, pipe_handle, tr_ptr))) { status = USB_OK; } else { printf("\nError in usb_class_hid_cntrl_common: %x", status); usb_host_release_tr(if_ptr->host_handle, tr_ptr); status = USBERR_ERROR; } break; case USB_SUBCLASS_COM_TELEPHONE: break; case USB_SUBCLASS_COM_MULTICHAN: break; case USB_SUBCLASS_COM_CAPI: break; case USB_SUBCLASS_COM_ETHERNET: break; case USB_SUBCLASS_COM_ATM_NET: break; } #ifdef _HOST_DEBUG_ if (!status) { DEBUG_LOG_TRACE("usb_class_cdc_cntrl_common, SUCCESSFUL"); } else { DEBUG_LOG_TRACE("usb_class_cdc_cntrl_common, FAILED"); } #endif return status; } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_cntrl_transaction_done * Returned Value : none * Comments : * Callback function to process transaction-done events * State machine for enumeration/subsequent transactions * Between states, the 8-byte buffer in device_instance * is used to save the first part of the configuration. * Pointer desc in various flavors (uint8_t *, cfig_ptr) * is used to parse this buffer in various ways. * *END*--------------------------------------------------------------------*/ static void usb_host_cntrl_transaction_done ( /* [IN] Unused */ void* tr_ptr, /* [IN] The user parameter */ void* user_parm, /* [IN] the buffer */ uint8_t * buffer, /* [IN] The length of the transfer */ uint32_t length, /* [IN] status of the transfer */ usb_status status ) { usb_host_state_struct_t* usb_host_ptr; dev_instance_t* dev_inst_ptr = (dev_instance_t*)user_parm; pipe_struct_t* pipe_ptr = dev_inst_ptr->control_pipe; descriptor_union_t desc; int32_t config_size = 0; uint32_t aligned_config_size = 0; usb_host_api_functions_struct_t* host_api; #ifdef USBCFG_OTG static bool otg_hnp_support; #endif usb_host_ptr = (usb_host_state_struct_t*)dev_inst_ptr->host; host_api = (usb_host_api_functions_struct_t*)usb_host_ptr->host_controller_api; if (usb_host_release_tr(usb_host_ptr, tr_ptr) != USB_OK) { printf("_usb_host_release_tr failed\n"); } switch (status) { case USB_OK: dev_inst_ptr->ctrl_retries = USBCFG_HOST_CTRL_RETRY; dev_inst_ptr->stall_retries = USBCFG_HOST_CTRL_RETRY; break; case USBERR_TR_FAILED: case USBERR_ENDPOINT_STALLED: //printf("TR failed buffer : %x\n\r", buffer); dev_inst_ptr->ctrl_retries--; dev_inst_ptr->stall_retries--; if ((status == USBERR_ENDPOINT_STALLED)&&(dev_inst_ptr->stall_retries)) { printf("USBERR_ENDPOINT_STALLED\n"); status = _usb_host_ch9_clear_feature((usb_device_instance_handle)dev_inst_ptr, REQ_TYPE_ENDPOINT, 0, ENDPOINT_HALT); } else if ((dev_inst_ptr->stall_retries == 0) || ((dev_inst_ptr->ctrl_retries)&&(status == USBERR_TR_FAILED))) { /* if hub level is 1 will do port reset */ if(dev_inst_ptr->level == 1) { host_api = (usb_host_api_functions_struct_t*)usb_host_ptr->host_controller_api; if (host_api->host_bus_control != NULL) { host_api->host_bus_control(usb_host_ptr->controller_handle, 1); } status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, 8, (uint8_t *)buffer); dev_inst_ptr->state = DEVSTATE_DEVDESC8; } else { #if USBCFG_HOST_HUB usb_host_hub_Port_Reset(dev_inst_ptr->hub_instance, dev_inst_ptr->port_no); usb_host_dev_mng_detach(dev_inst_ptr->host, dev_inst_ptr->hub_no, dev_inst_ptr->port_no); #endif } } break; default: break; } if (status != USB_OK) { return; } /*----------------------------------------------------** ** Enumeration state machine -- cases are named after ** ** the just-completed transactions. ** **----------------------------------------------------*/ switch (dev_inst_ptr->state) { case DEVSTATE_INITIAL: /* initial device state = forever error state */ break; case DEVSTATE_DEVDESC8: /* device descriptor [0..7]*/ /* We must have received the first 8 bytes in * dev_inst_ptr->dev_descriptor which contains the * max packet size for this control endpoint */ //printf("dev8\n"); pipe_ptr->max_packet_size = dev_inst_ptr->dev_descriptor.bMaxPacketSize; //printf("DEVSTATE_DEVDESC8 %d\n",dev_inst_ptr->dev_descriptor.bMaxPacketSize); /* Notify device driver of MaxPacketSize0 for this device */ status = _usb_host_update_max_packet_size_call_interface (usb_host_ptr, pipe_ptr); if (status != USB_OK) { printf("update max packet size error\n"); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } else { dev_inst_ptr->state = DEVSTATE_ADDR_SET; } /* Now set the address that we assigned when we initialized * the device instance struct for this device */ status = _usb_host_ch9_set_address((usb_device_instance_handle)dev_inst_ptr); if (status != USB_OK) { printf("set address error\n"); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } break; case DEVSTATE_ADDR_SET: /* address set */ //pipe_ptr->DEVICE_ADDRESS = dev_inst_ptr->address; // printf("add set %d\n", dev_inst_ptr->target_address); dev_inst_ptr->address = dev_inst_ptr->target_address; /* Notify device driver of USB device's new address */ status = _usb_host_update_device_address_call_interface (usb_host_ptr, pipe_ptr); if (status != USB_OK) { printf("update device address error\n"); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } dev_inst_ptr->state = DEVSTATE_DEV_DESC; //printf("descriptor address 0x%x\n", &dev_inst_ptr->dev_descriptor); /* Now get the full descriptor */ status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, USB_DESC_LEN_DEV, (uint8_t *)&dev_inst_ptr->dev_descriptor); if (status != USB_OK) { printf("get device descriptor error\n"); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } break; case DEVSTATE_DEV_DESC: /* full device descriptor received */ /* Now lets get the first 9 bytes of the configuration descriptor */ desc.pntr = &dev_inst_ptr->buffer; //printf("dev %d cfg, c %d 0x%x\n", dev_inst_ptr->dev_descriptor.bNumConfigurations, dev_inst_ptr->cfg_value, desc.pntr); dev_inst_ptr->state = DEVSTATE_GET_CFG9; status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)dev_inst_ptr, USB_DESC_TYPE_CFG << 8 | dev_inst_ptr->cfg_value, 0, sizeof(dev_inst_ptr->buffer), desc.bufr); if (status != USB_OK) { printf("get 9 byte configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } break; case DEVSTATE_GET_CFG9: /* Read 9 bytes of config descriptor */ /* Now select the configuration as specified in the * descriptor */ desc.cfig = (usb_configuration_descriptor_t*)dev_inst_ptr->buffer; config_size = USB_SHORT_UNALIGNED_LE_TO_HOST(desc.cfig->wTotalLength); /* for KHCI, the start address and the length should be 4 byte align */ if ((config_size && 0x3) != 0) { aligned_config_size = (config_size & 0xFFFFFFFC) + 4; } if (dev_inst_ptr->lpConfiguration != NULL) { OS_Mem_free(dev_inst_ptr->lpConfiguration); dev_inst_ptr->lpConfiguration = NULL; } dev_inst_ptr->lpConfiguration = (void*)OS_Mem_alloc_uncached(aligned_config_size); if (dev_inst_ptr->lpConfiguration == NULL) { printf("get memory for full configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } //printf("Get CFG9 %d %d %d\n",dev_inst_ptr->cfg_value, config_size,dev_inst_ptr->dev_descriptor.bNumConfigurations); /* We can only read one config descriptor at a time */ status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)dev_inst_ptr, (USB_DESC_TYPE_CFG << 8) | dev_inst_ptr->cfg_value, 0, (uint16_t)config_size, dev_inst_ptr->lpConfiguration); if (status != USB_OK) { printf("get full configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } #ifdef USBCFG_OTG dev_inst_ptr->state = DEVSTATE_CHK_OTG; #else /*dev_inst_ptr->state = DEVSTATE_SET_CFG;*/ dev_inst_ptr->state = DEVSTATE_CFG_READ; #endif break; #ifdef USBCFG_OTG case DEVSTATE_CHK_OTG: otg_hnp_support = FALSE; /* Point to the memory owned by this device */ /* FIXME: it is presumed that memlist points to the config descriptor */ desc.pntr = dev_inst_ptr->lpConfiguration; /* We will always start with config desc so update the search pointer */ config_size = USB_SHORT_UNALIGNED_LE_TO_HOST(desc.cfig->wTotalLength); config_size -= desc.cfig->bLength; desc.word += desc.cfig->bLength; while (config_size) { if (desc.otg->bDescriptorType == USB_DESC_TYPE_OTG) { /* Found the OTG descriptor */ break; } config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } /* Check for an OTG descriptor */ dev_inst_ptr->state = DEVSTATE_CFG_READ; if (config_size && desc.otg->bDescriptorType == USB_DESC_TYPE_OTG && (desc.otg->bmAttributes & OTG_HNP_SUPPORT)) { otg_hnp_support = TRUE; if(_usb_otg_host_get_otg_attribute(usb_host_ptr->otg_handle,desc.otg->bmAttributes) == USB_OK) { if(_usb_otg_host_set_feature_required(usb_host_ptr->otg_handle)) { status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_A_HNP_SUPPORT); if (status != USB_OK) { printf("set feature for otg error\n"); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } else { dev_inst_ptr->state = DEVSTATE_SET_HNP; break; } } } } case DEVSTATE_SET_HNP: if (otg_hnp_support) { status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_B_HNP_ENABLE); if (status != USB_OK) { dev_inst_ptr->state = DEVSTATE_INITIAL; } else { dev_inst_ptr->state = DEVSTATE_SET_HNP_OK; } break; } case DEVSTATE_SET_HNP_OK: if(dev_inst_ptr->state == DEVSTATE_SET_HNP_OK) { _usb_otg_host_a_set_b_hnp_en(usb_host_ptr->otg_handle, TRUE); } #endif case DEVSTATE_CFG_READ: dev_inst_ptr->cfg_value++; //printf("cfg %d, %d\n", dev_inst_ptr->cfg_value,dev_inst_ptr->dev_descriptor.bNumConfigurations); if (usb_host_dev_mng_parse_configuration_descriptor(dev_inst_ptr) == USB_OK) { //printf("parse cfg\n"); if (usb_host_dev_mng_check_configuration(dev_inst_ptr)) { //printf("check cfg\n"); usb_host_dev_notify(dev_inst_ptr, USB_ATTACH_EVENT); /* enumeration done */ dev_inst_ptr->state = DEVSTATE_SET_CFG; /* send set_configuration */ status = _usb_host_ch9_set_configuration(dev_inst_ptr, dev_inst_ptr->configuration.lpconfigurationDesc->bConfigurationValue); if (status != USB_OK) { printf("set configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } } else { //printf("cfg %d %d\n", dev_inst_ptr->cfg_value,dev_inst_ptr->dev_descriptor.bNumConfigurations); /* get next configuration */ if (dev_inst_ptr->cfg_value < dev_inst_ptr->dev_descriptor.bNumConfigurations) { //printf("invalid cfg re\n"); desc.pntr = &dev_inst_ptr->buffer; dev_inst_ptr->state = DEVSTATE_GET_CFG9; status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)dev_inst_ptr, USB_DESC_TYPE_CFG << 8 | dev_inst_ptr->cfg_value, 0, sizeof(dev_inst_ptr->buffer), desc.bufr); if (status != USB_OK) { printf("get 9 byte configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } } else { printf("unsupported device attached\n"); usb_host_dev_notify(dev_inst_ptr, USB_ATTACH_DEVICE_NOT_SUPPORT); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } } } else { printf("parse configuration(%d) error\n", dev_inst_ptr->cfg_value); usb_host_dev_mng_pre_detach(dev_inst_ptr->host,dev_inst_ptr->hub_no,dev_inst_ptr->port_no); break; } break; case DEVSTATE_SET_CFG: /* config descriptor [0..8] */ dev_inst_ptr->state = DEVSTATE_ENUM_OK; usb_host_dev_notify(dev_inst_ptr, USB_CONFIG_EVENT); #ifdef USBCFG_OTG _usb_otg_host_on_interface_event(usb_host_ptr->otg_handle, dev_inst_ptr); #endif break; case DEVSTATE_SET_INTF: /* Select interface done */ dev_inst_ptr->state = DEVSTATE_ENUM_OK; usb_host_dev_notify(dev_inst_ptr, USB_INTF_OPENED_EVENT); break; case DEVSTATE_ENUM_OK: /* enumeration complete */ if ((dev_inst_ptr->control_callback != NULL)) { dev_inst_ptr->control_callback(tr_ptr, dev_inst_ptr->control_callback_param, buffer, length, status); } break; default: break; } /* EndSwitch */ } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_audio_cntrl_common * Returned Value : USB_OK if command has been passed on USB. * Comments : * This function is used to send a control request. * It must be run with USB locked. * *END*--------------------------------------------------------------------*/ static usb_status usb_class_audio_cntrl_common ( /* [IN] The communication device common command structure */ audio_command_t* com_ptr, /* [IN] The audio control interface */ //audio_control_struct_t* if_ctrl_ptr, /* [IN] Bitmask of the request type */ uint8_t bmrequesttype, /* [IN] Request code */ uint8_t brequest, /* [IN] Value to copy into wvalue field of the REQUEST */ uint16_t wvalue, /* [IN] Value to copy into windex field of the REQUEST */ uint16_t windex, /* [IN] Length of the data associated with REQUEST */ uint16_t wlength, /* [IN] Pointer to data buffer used to send/recv */ uint8_t * data ) { /* Body */ audio_control_struct_t* audio_class = NULL; //usb_setup_t req; usb_status status = USB_OK; usb_pipe_handle pipe_handle; tr_struct_t* tr_ptr; if ((com_ptr == NULL) || (com_ptr->class_control_handle == NULL)) { return USBERR_ERROR; } audio_class = (audio_control_struct_t*)com_ptr->class_control_handle; if (audio_class->in_setup) { return USBERR_TRANSFER_IN_PROGRESS; } if (audio_class->dev_handle == NULL) { return USB_log_error(__FILE__,__LINE__,USBERR_DEVICE_NOT_FOUND); } audio_class->ctrl_callback = com_ptr->callback_fn; audio_class->ctrl_param = com_ptr->callback_param; pipe_handle = usb_host_dev_mng_get_control_pipe(audio_class->dev_handle); if (usb_host_get_tr(audio_class->host_handle, usb_class_audio_cntrl_callback, audio_class, &tr_ptr) != USB_OK) { USB_PRINTF("error to get tr audio \r\n"); return USBERR_ERROR; } /* Set TR buffer length as required */ if ((REQ_TYPE_IN & bmrequesttype) != 0) { tr_ptr->rx_buffer = data; tr_ptr->rx_length = wlength; } else { tr_ptr->tx_buffer = data; tr_ptr->tx_length = wlength; } tr_ptr->setup_packet.bmrequesttype = bmrequesttype; tr_ptr->setup_packet.brequest = brequest; *(uint16_t*)&(tr_ptr->setup_packet.wvalue[0]) = USB_HOST_TO_LE_SHORT(wvalue); *(uint16_t*)&(tr_ptr->setup_packet.windex[0]) = USB_HOST_TO_LE_SHORT(windex); //USB_HOST_TO_LE_SHORT(((interface_descriptor_t*)(audio_class->intf_handle))->bInterfaceNumber); *(uint16_t*)&(tr_ptr->setup_packet.wlength[0]) = USB_HOST_TO_LE_SHORT(wlength); audio_class->in_setup = TRUE; status = usb_host_send_setup(audio_class->host_handle, pipe_handle, tr_ptr); if (status != USB_OK) { audio_class->in_setup = FALSE; USB_PRINTF("\nError in usb_class_audio_cntrl_common: %x", (unsigned int)status); usb_host_release_tr(audio_class->host_handle, tr_ptr); } return status; } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_hub_recv_bitmap * Returned Value : None * Comments : * Starts interrupt endpoint to poll for interrupt on specified hub *END*--------------------------------------------------------------------*/ usb_status usb_class_hub_recv_bitmap ( /* [IN] Class Interface structure pointer */ hub_command_t* com_ptr, /* [IN] The buffer address */ uint8_t * buffer, /* size of buffer to be used */ uint8_t length ) { usb_hub_class_struct_t* hub_class; tr_struct_t* tr_ptr; usb_status status = USBERR_NO_INTERFACE; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_hub_recv_bitmap"); #endif //USB_PRINTF("r \n"); if ((com_ptr == NULL) || (com_ptr->class_ptr == NULL)) { return USBERR_ERROR; } hub_class = (usb_hub_class_struct_t*)com_ptr->class_ptr; if ((hub_class == NULL) || (buffer == NULL)) { USB_PRINTF("input parameter error\n"); return USBERR_ERROR; } hub_class->interrupt_callback = com_ptr->callback_fn; hub_class->interrupt_param = com_ptr->callback_param; if (hub_class->dev_handle == NULL) { return USBERR_ERROR; } if (hub_class->in_interrupt) { return USBERR_ERROR; } if (usb_host_get_tr(hub_class->host_handle, usb_class_hub_int_callback, hub_class, &tr_ptr) != USB_OK) { USB_PRINTF("error to get tr\n"); return USBERR_ERROR; } tr_ptr->rx_buffer = buffer; tr_ptr->rx_length = length; status = usb_host_recv_data(hub_class->host_handle, hub_class->interrupt_pipe, tr_ptr); if (status != USB_OK) { USB_PRINTF("\nError in usb_class_hub_recv_bitmap: %x", (unsigned int)status); usb_host_release_tr(hub_class->host_handle, tr_ptr); return USBERR_ERROR; } hub_class->in_interrupt = TRUE; return USB_OK; }
usb_status usb_class_hub_cntrl_common ( /* [IN] Class Interface structure pointer */ hub_command_t* com_ptr, /* [IN] Bitmask of the request type */ uint8_t bmrequesttype, /* [IN] Request code */ uint8_t brequest, /* [IN] Value to copy into wvalue field of the REQUEST */ uint16_t wvalue, /* [IN] Length of the data associated with REQUEST */ uint16_t windex, /* [IN] Index field of CTRL packet */ uint16_t wlength, /* [IN] the buffer to be transfered */ uint8_t * data ) { usb_hub_class_struct_t* hub_class = NULL; //usb_setup_t req; usb_status status = USB_OK; tr_struct_t* tr_ptr; if ((com_ptr == NULL) || (com_ptr->class_ptr == NULL)) { return USBERR_ERROR; } hub_class = (usb_hub_class_struct_t*)com_ptr->class_ptr; if (hub_class->in_setup) { return USBERR_TRANSFER_IN_PROGRESS; } if (hub_class->dev_handle == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_hub_cntrl_common, invalid device handle"); #endif return USBERR_DEVICE_NOT_FOUND; } hub_class->ctrl_callback = com_ptr->callback_fn; hub_class->ctrl_param = com_ptr->callback_param; if (usb_host_get_tr(hub_class->host_handle, usb_class_hub_cntrl_callback, hub_class, &tr_ptr) != USB_OK) { USB_PRINTF("error to get tr hub\n"); return USBERR_ERROR; } /* Set TR buffer length as required */ if ((REQ_TYPE_IN & bmrequesttype) != 0) { tr_ptr->rx_buffer = data; tr_ptr->rx_length = wlength; } else { tr_ptr->tx_buffer = data; tr_ptr->tx_length = wlength; } tr_ptr->setup_packet.bmrequesttype = bmrequesttype; tr_ptr->setup_packet.brequest = brequest; *(uint16_t*)tr_ptr->setup_packet.wvalue = USB_HOST_TO_LE_SHORT(wvalue); *(uint16_t*)tr_ptr->setup_packet.windex = USB_HOST_TO_LE_SHORT(windex); *(uint16_t*)tr_ptr->setup_packet.wlength = USB_HOST_TO_LE_SHORT(wlength); status = usb_host_send_setup(hub_class->host_handle, hub_class->control_pipe, tr_ptr); if (status != USB_OK) { usb_host_release_tr(hub_class->host_handle, tr_ptr); return USBERR_ERROR; } hub_class->in_setup = TRUE; return USB_OK; } /* Endbody */