/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_hub_deinit * Returned Value : None * Comments : * This function is called by common class to deinitialize the class driver. It * is called in response to a select interface call by application * *END*--------------------------------------------------------------------*/ usb_status usb_class_hub_deinit ( /* [IN] the class driver handle */ class_handle handle ) { usb_hub_class_struct_t* hub_class = (usb_hub_class_struct_t*)handle; usb_status status = USB_OK; if (hub_class == NULL) { USB_PRINTF("usb_class_hid_deinit fail\n"); return USBERR_ERROR; } if (hub_class->interrupt_pipe != NULL) { status = usb_host_close_pipe(hub_class->host_handle, hub_class->interrupt_pipe); if (status != USB_OK) { USB_PRINTF("error in usb_class_hid_deinit to close pipe\n"); } } OS_Mem_free(handle); //USB_PRINTF("HID class driver de-initialized\n"); return USB_OK; } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_video_control_deinit * Returned Value : None * Comments : * This function is called by common class to initialize the class driver. It * is called in response to a select interface call by application * *END*--------------------------------------------------------------------*/ usb_status usb_class_video_control_deinit ( /* [IN] the class driver handle */ class_handle handle ) { usb_video_control_struct_t* video_control_ptr = (usb_video_control_struct_t*)handle; usb_status status = USB_OK; if (video_control_ptr == NULL) { #ifdef _DEBUG USB_PRINTF("usb_class_video_control_deinit fail\n"); #endif return USBERR_ERROR; } if (video_control_ptr->control_interrupt_in_pipe != NULL) { status = usb_host_close_pipe(video_control_ptr->host_handle, video_control_ptr->control_interrupt_in_pipe); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("error in usb_class_video_control_deinit to close pipe\n"); #endif } } OS_Mem_free(handle); //USB_PRINTF("Video class driver de-initialized\n"); return USB_OK; } /* Endbody */
usb_status usb_class_cdc_acm_deinit ( /* [IN] acm call struct pointer */ class_handle handle ) { usb_acm_class_intf_struct_t * acm_class_intf = (usb_acm_class_intf_struct_t *)handle; usb_status status = USB_OK; if (acm_class_intf == NULL) { printf("usb_class_cdc_acm_deinit fail\n"); return USBERR_ERROR; } if (acm_class_intf->interrupt_pipe != NULL) { status = usb_host_close_pipe(acm_class_intf->host_handle, acm_class_intf->interrupt_pipe); if (status != USB_OK) { printf("error in usb_class_cdc_acm_deinit to close pipe\n"); } } if (acm_class_intf->acm_event != NULL) { OS_Event_set(acm_class_intf->acm_event, USB_ACM_DETACH); /* mark we are not using input pipe */ } OS_Mutex_destroy(acm_class_intf->mutex); OS_Mem_free(handle); return USB_OK; /* destroying lwevent is up to application */ }
usb_status usb_class_cdc_data_deinit ( /* [IN] data call struct pointer */ class_handle handle ) { usb_data_class_intf_struct_t * data_class_intf = (usb_data_class_intf_struct_t *)handle; usb_status status = USB_OK; if (data_class_intf == NULL) { printf("usb_class_cdc_data_deinit fail\n"); return USBERR_ERROR; } if (data_class_intf->in_pipe != NULL) { status = usb_host_close_pipe(data_class_intf->host_handle, data_class_intf->in_pipe); if (status != USB_OK) { printf("error in usb_class_cdc_data_deinit to close pipe\n"); } } if (data_class_intf->out_pipe != NULL) { status = usb_host_close_pipe(data_class_intf->host_handle, data_class_intf->out_pipe); if (status != USB_OK) { printf("error in usb_class_cdc_data_deinit to close pipe\n"); } } if ((data_class_intf->in_pipe != NULL) && (data_class_intf->data_event != NULL)) OS_Event_set(data_class_intf->data_event, USB_DATA_DETACH); /* mark we are not using input pipe */ if (data_class_intf->rx_buffer != NULL) { OS_Mem_free(data_class_intf->rx_buffer); } OS_Mutex_destroy(data_class_intf->mutex); OS_Mem_free(handle); return status; /* destroying lwevent is up to application */ } /* Endbody */
/*FUNCTION*------------------------------------------------------------------- * * Function Name : usb_otg_shut_down * Returned Value : de-initialization status * Comments : De-Initializes OTG stack * * *END*----------------------------------------------------------------------*/ usb_status usb_otg_shut_down ( /*[IN] address of the OTG interface structure */ usb_otg_handle otg_handle ) { usb_status error = USB_OK; usb_otg_state_struct_t * usb_otg_ptr = g_usb_otg_handle; const usb_otg_api_functions_struct_t * otg_api = NULL; if ((otg_handle == NULL) || (usb_otg_ptr == NULL)) { #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("_usb_otg_init invalid parameters"); #endif return USBERR_ERROR; } otg_api = usb_otg_ptr->otg_controller_api; if (otg_api == NULL) { return USBERR_ERROR; } error = _usb_otg_task_delete(usb_otg_ptr); if (error != USB_OK) { #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("usb_otg_shut_down _usb_otg_task_delete failure"); #endif return USBERR_ALLOC; } /* Initialize the USB interface. */ if (otg_api->otg_shutdown != NULL) { error = otg_api->otg_shutdown(usb_otg_ptr); if (error) { #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("usb_otg_shut_down otg_shutdown failure"); #endif return USBERR_ALLOC; } } usb_otg_ptr->init_struct = NULL; OS_Event_destroy(usb_otg_ptr->otg_app_event); OS_Event_destroy(usb_otg_ptr->otg_isr_event); usb_otg_ptr->device_state = USB_OTG_DEVSTATE_UNDEFINED; usb_otg_ptr->sub_state = USB_OTG_SM_UNDEFINED; usb_otg_ptr->power_up = FALSE; OS_Mem_free(usb_otg_ptr); usb_otg_ptr = NULL; return USB_OK; }
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_dev_mng_detach * Returned Value : * Comments : * This function will be called when detach interrupt happens. * *END*--------------------------------------------------------------------*/ usb_status usb_host_dev_mng_detach ( usb_host_handle handle, uint8_t hub_no, uint8_t port_no ) { /* Body */ usb_host_state_struct_t* usb_host_ptr = (usb_host_state_struct_t*)handle; dev_instance_t* dev_instance_ptr; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_detach"); #endif usb_host_dev_mng_pre_detach(handle, hub_no, port_no); /* search device list for the one being detached */ USB_Host_lock(); dev_instance_ptr = (dev_instance_t*)usb_host_dev_get_instance(handle, hub_no, port_no, (uint8_t)1); if (dev_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_detach NULL device pointer"); #endif USB_Host_unlock(); return USBERR_ERROR; /* No match, abandon ship! */ } dev_instance_ptr->attached = (uint8_t)FALSE; USB_Host_unlock(); if (dev_instance_ptr->state > DEVSTATE_SET_CFG) { /* Notify the application of unavailable interfaces */ usb_host_dev_notify(dev_instance_ptr,USB_DETACH_EVENT); #ifdef USBCFG_OTG _usb_otg_host_on_detach_event(usb_host_ptr->otg_handle); #endif } else { OS_Mem_free(dev_instance_ptr); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_detach SUCCESSFUL"); #endif return USB_OK; } /* EndBody */
/*FUNCTION*------------------------------------------------------------- * * Function Name : usb_device_deinit * Returned Value : USB_OK or error code * Comments : * uninitializes the USB device specific data structures and calls * the low-level device controller chip initialization routine. * *END*-----------------------------------------------------------------*/ usb_status usb_device_deinit ( /* [OUT] the USB_USB_dev_initialize state structure */ usb_device_handle handle ) { #if (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_MQX) uint32_t i; #endif usb_dev_state_struct_t* usb_dev_ptr; //usb_class_fw_object_struct_t* usb_fw_ptr = NULL; if (handle == NULL) { #if _DEBUG printf("_usb_device_shutdowna: handle is NULL\n"); #endif return USBERR_ERROR; } usb_dev_ptr = (usb_dev_state_struct_t*)handle; OS_Mutex_destroy(usb_dev_ptr->mutex); _usb_device_shutdown(handle); _usb_device_release_handle(usb_dev_ptr); #if (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_MQX) for(i = 0; i < USBCFG_DEV_NUM; i++) { if(NULL != g_usb_dev_data_ptr[i]) { OS_Mem_free(g_usb_dev_data_ptr[i]); g_usb_dev_data_ptr[i] = NULL; } } #endif return USB_OK; } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : Keyboard_Task * Returned Value : none * Comments : * Execution starts here * *END*--------------------------------------------------------------------*/ void Keyboard_Task(void* param) { usb_status status = USB_OK; static uint8_t i = 0; usb_host_handle kbd_host_handle = (usb_host_handle) param; uint8_t j = 0; // Wait for insertion or removal event OS_Event_wait(kbd_usb_event, USB_EVENT_CTRL | USB_EVENT_DATA | USB_EVENT_DATA_CORRUPTED | USB_EVEN_OUTPUT | USB_EVENT_STATE_CHANGE, FALSE, 0); if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_STATE_CHANGE)) { OS_Event_clear(kbd_usb_event, USB_EVENT_STATE_CHANGE); update_state(); } if (OS_Event_check_bit(kbd_usb_event, USB_EVEN_OUTPUT)) { OS_Event_clear(kbd_usb_event, USB_EVEN_OUTPUT); if (detach == 1) { /*clear the keyboard flag value*/ for (j = 8 - 1; j >= 2; j--) { flag[j] = 0; } } for (j = 2; j < 8; j++) { if ((buffer_timer[j] == flag[j]) && ((g_current_time - flag_time[j]) > KB_CONTINUE_PRESS)) { if (flag[j] > 1) { usb_host_hid_keyboard_output_keyvalue(flag[j]); } } } if (!OS_Event_check_bit(kbd_usb_event, USB_EVENT_CTRL | USB_EVENT_DATA | USB_EVENT_DATA_CORRUPTED)) { return; } } if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_CTRL)) { OS_Event_clear(kbd_usb_event, USB_EVENT_CTRL); } switch(kbd_hid_device.DEV_STATE) { case USB_DEVICE_IDLE: break; case USB_DEVICE_ATTACHED: USB_PRINTF("\r\nKeyboard device attached\r\n"); kbd_hid_device.DEV_STATE = USB_DEVICE_SET_INTERFACE_STARTED; status = usb_host_open_dev_interface(kbd_host_handle, kbd_hid_device.DEV_HANDLE, kbd_hid_device.INTF_HANDLE, (usb_class_handle*) &kbd_hid_device.CLASS_HANDLE); if (status != USB_OK) { USB_PRINTF("\r\nError in _usb_hostdev_open_interface: %x\r\n", status); return; } break; case USB_DEVICE_INTERFACE_OPENED: kbd_hid_get_report_descriptor(); break; case USB_DEVICE_GET_REPORT_DESCRIPTOR_DONE: kbd_hid_get_buffer(); USB_PRINTF("Keyboard interfaced, setting protocol...\r\n"); /* now we will set the USB Hid standard boot protocol */ kbd_hid_device.DEV_STATE = USB_DEVICE_SETTING_PROTOCOL; kbd_hid_com->class_ptr = kbd_hid_device.CLASS_HANDLE; kbd_hid_com->callback_fn = usb_host_hid_keyboard_ctrl_callback; kbd_hid_com->callback_param = 0; status = usb_class_hid_set_protocol(kbd_hid_com, USB_PROTOCOL_HID_KEYBOARD); if (status != USB_OK) { USB_PRINTF("\r\nError in usb_class_hid_set_protocol: %x\r\n", status); } break; case USB_DEVICE_SET_INTERFACE_STARTED: break; case USB_DEVICE_INUSE: //USB_PRINTF("%d\n", data_received); i++; if (kbd_data_received) { /****************************************************************** Initiate a transfer request on the interrupt pipe ******************************************************************/ kbd_hid_com->class_ptr = kbd_hid_device.CLASS_HANDLE; kbd_hid_com->callback_fn = usb_host_hid_keyboard_recv_callback; kbd_hid_com->callback_param = 0; if (i == 4) { sleep_test = TRUE; } status = usb_class_hid_recv_data(kbd_hid_com, kbd_buffer, kbd_size); if (sleep_test) { sleep_test = FALSE; } if (status != USB_OK) { USB_PRINTF("\r\nError in usb_class_hid_recv_data: %x", status); } else { //USB_PRINTF("try to get recv data\n"); kbd_data_received = 0; } } /* Wait until we get the data from keyboard. */ if (OS_Event_wait(kbd_usb_event, USB_EVENT_CTRL | USB_EVENT_DATA | USB_EVENT_DATA_CORRUPTED, FALSE, 0) == OS_EVENT_OK) { if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_DATA)) { //USB_PRINTF("get data\n"); OS_Event_clear(kbd_usb_event, USB_EVENT_DATA); kbd_data_received = 1; if (kbd_hid_device.DEV_STATE == USB_DEVICE_INUSE) { process_kbd_buffer((uint8_t *) kbd_buffer); } status = usb_class_hid_recv_data(kbd_hid_com, kbd_buffer, kbd_size); if (status != USB_OK) { USB_PRINTF("\r\nError in usb_class_hid_recv_data: %x", status); } else { //USB_PRINTF("try to get recv data\n"); kbd_data_received = 0; } } if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_DATA_CORRUPTED)) { //USB_PRINTF("get corrupted\n"); kbd_data_received = 1; OS_Event_clear(kbd_usb_event, USB_EVENT_DATA_CORRUPTED); status = usb_class_hid_recv_data(kbd_hid_com, kbd_buffer, kbd_size); if (status != USB_OK) { USB_PRINTF("\r\nError in usb_class_hid_recv_data: %x", status); } else { //USB_PRINTF("try to get recv data\n"); kbd_data_received = 0; } } if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_CTRL)) { //USB_PRINTF("get control\n"); //OS_Event_set(USB_Event, USB_EVENT_CTRL); } } break; case USB_DEVICE_DETACHED: if (kbd_data_received == 1) { status = usb_host_close_dev_interface(kbd_host_handle, kbd_hid_device.DEV_HANDLE, kbd_hid_device.INTF_HANDLE, kbd_hid_device.CLASS_HANDLE); if (status != USB_OK) { USB_PRINTF("error in _usb_hostdev_close_interface %x\r\n", status); } kbd_hid_device.INTF_HANDLE = NULL; kbd_hid_device.CLASS_HANDLE = NULL; USB_PRINTF("Going to idle state\r\n"); kbd_hid_device.DEV_STATE = USB_DEVICE_IDLE; if (kbd_reportDescriptor != NULL) { OS_Mem_free(kbd_reportDescriptor); kbd_reportDescriptor = NULL; } if (kbd_buffer != NULL) { OS_Mem_free(kbd_buffer); kbd_buffer = NULL; } } else { if (OS_Event_wait(kbd_usb_event, USB_EVENT_CTRL | USB_EVENT_DATA | USB_EVENT_DATA_CORRUPTED, FALSE, 0) == OS_EVENT_OK) { if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_DATA)) { //USB_PRINTF("get data\n"); OS_Event_clear(kbd_usb_event, USB_EVENT_DATA); kbd_data_received = 1; if (kbd_hid_device.DEV_STATE == USB_DEVICE_INUSE) { process_kbd_buffer((uint8_t *) kbd_buffer); OS_Mem_zero(kbd_buffer, kbd_size); } } if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_DATA_CORRUPTED)) { //USB_PRINTF("get corrupted\n"); kbd_data_received = 1; OS_Event_clear(kbd_usb_event, USB_EVENT_DATA_CORRUPTED); } if (OS_Event_check_bit(kbd_usb_event, USB_EVENT_CTRL)) { //USB_PRINTF("get control\n"); //OS_Event_set(USB_Event, USB_EVENT_CTRL); } } OS_Event_set(kbd_usb_event, USB_EVENT_CTRL); } break; case USB_DEVICE_OTHER: break; default: break; } /* Endswitch */ }
/*FUNCTION*---------------------------------------------------------------- * * Function Name : kbd_hid_get_buffer * Returned Value : none * Comments : * Find and parse the HID descriptor, then try to get the report descriptor. * *END*--------------------------------------------------------------------*/ void kbd_hid_get_report_descriptor(void) { usb_status status = USB_OK; usb_device_interface_struct_t* interfaceDescriptor = (usb_device_interface_struct_t*) kbd_hid_get_interface(); descriptor_union_t ptr1, ptr2; ptr1.pntr = interfaceDescriptor->interfaceEx; ptr2.word = ptr1.word + interfaceDescriptor->interfaceExlength; while (ptr1.cfig->bDescriptorType != USB_DESC_TYPE_HID) { ptr1.word += ptr1.cfig->bLength; if (ptr1.word >= ptr2.word) { break; } } if (ptr1.word < ptr2.word) { hid_descriptor_struct_t* hidDescriptor = (hid_descriptor_struct_t*) ptr1.pntr; hid_class_descriptor_struct_t* hidClassDescriptor = (hid_class_descriptor_struct_t*) &(hidDescriptor->bclassdescriptortype); uint8_t index; kbd_reportLength = 0; for (index = 0; index < hidDescriptor->bnumdescriptor; index++) { hid_class_descriptor_struct_t* temp; temp = hidClassDescriptor + index; if (temp->classdescriptortype == USB_DESC_TYPE_REPORT) { kbd_reportLength = USB_SHORT_UNALIGNED_LE_TO_HOST(temp->descriptorlength); break; } } if (kbd_reportLength != 0) { if (kbd_reportDescriptor != NULL) { OS_Mem_free(kbd_reportDescriptor); } kbd_reportDescriptor = (uint8_t*) OS_Mem_alloc_uncached_zero(kbd_reportLength); if (kbd_reportDescriptor == NULL) { USB_PRINTF("allocate memory failed in hid_get_buffer\r\n"); return; } kbd_hid_device.DEV_STATE = USB_DEVICE_GET_REPORT_DESCRIPTOR; kbd_hid_com->class_ptr = kbd_hid_device.CLASS_HANDLE; kbd_hid_com->callback_fn = usb_host_hid_keyboard_ctrl_callback; kbd_hid_com->callback_param = 0; status = usb_class_hid_get_descriptor(kbd_hid_com, (uint8_t) USB_DESC_TYPE_REPORT, kbd_reportDescriptor, kbd_reportLength); if (status != USB_OK) { USB_PRINTF("\r\nError in usb_class_hid_get_descriptor: %x\r\n", status); } } } else { USB_PRINTF("Can't find HID_DESCRIPTOR\r\n"); } return; }
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_dev_mng_pre_detach * Returned Value : * Comments : * This function will be called when detach interrupt happens. * *END*--------------------------------------------------------------------*/ usb_status usb_host_dev_mng_pre_detach ( usb_host_handle handle, uint8_t hub_no, uint8_t port_no ) { /* Body */ usb_host_state_struct_t* usb_host_ptr = (usb_host_state_struct_t*)handle; dev_instance_t* dev_instance_ptr; uint8_t interface_index; interface_descriptor_t* intf = NULL; usb_device_interface_info_struct_t* lpinterface_info = NULL; class_map_t* class_map; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_pre_detach"); #endif /* search device list for the one being detached */ USB_Host_lock(); dev_instance_ptr = (dev_instance_t*)usb_host_dev_get_instance(handle, hub_no, port_no, (uint8_t)0); if (dev_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_pre_detach NULL device pointer"); #endif USB_Host_unlock(); return USBERR_ERROR; /* No match, abandon ship! */ } if (dev_instance_ptr->pre_detached == (uint8_t)TRUE) { USB_Host_unlock(); return USB_OK; } if (NULL != dev_instance_ptr->control_pipe) { /* Close control pipe */ usb_host_cancel(handle, (pipe_struct_t*)dev_instance_ptr->control_pipe, (tr_struct_t*)NULL); } for (interface_index = 0; interface_index < dev_instance_ptr->configuration.interface_count; interface_index++) { intf = dev_instance_ptr->configuration.interface[interface_index].lpinterfaceDesc; lpinterface_info = usb_host_dev_mng_get_interface_info(dev_instance_ptr, intf); if (lpinterface_info == NULL) { continue; } class_map = lpinterface_info->lpClassDriverMap; if (class_map != NULL) { class_map->class_pre_deinit(lpinterface_info->lpClassHandle); } } dev_instance_ptr->pre_detached = (uint8_t)TRUE; USB_Host_unlock(); if (dev_instance_ptr->state <= DEVSTATE_SET_CFG) { if (dev_instance_ptr->control_pipe != NULL) { usb_host_close_pipe(dev_instance_ptr->host, dev_instance_ptr->control_pipe); dev_instance_ptr->control_pipe = NULL; } if (dev_instance_ptr->lpConfiguration != NULL) { OS_Mem_free(dev_instance_ptr->lpConfiguration); dev_instance_ptr->lpConfiguration = NULL; } } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_dev_mng_pre_detach SUCCESSFUL"); #endif return USB_OK; } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_dev_mng_attach * Returned Value : * Comments : * This function will be called when attach interrupt happens, to * add onto the device list and do common initialization. * *END*--------------------------------------------------------------------*/ usb_status usb_host_dev_mng_attach ( usb_host_handle handle, hub_device_struct_t* hub_instance, uint8_t speed, uint8_t hub_no, uint8_t port_no, uint8_t level, usb_device_instance_handle* handle_ptr ) { usb_status status; dev_instance_t* new_instance_ptr; dev_instance_t* dev_instance_ptr; dev_instance_t* dev_instance_prev_ptr; usb_host_state_struct_t* usb_host_ptr; //dev_instance_t* device_root = NULL; pipe_init_struct_t pipe_init; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device attach device"); #endif usb_host_ptr = (usb_host_state_struct_t*)handle; //printf("a %d %d %d\n", hub_no, port_no, level); /* Allocate new device instance */ new_instance_ptr = (dev_instance_t*) OS_Mem_alloc_uncached_zero(sizeof(dev_instance_t)); if (new_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device failed to malloc device handle"); #endif printf("memory allocation failed in usb_host_dev_mng_attach\n"); return USB_log_error(__FILE__,__LINE__, USBERR_GET_MEMORY_FAILED); } /* EndIf */ new_instance_ptr->host = handle; new_instance_ptr->speed = speed; new_instance_ptr->hub_instance = hub_instance; new_instance_ptr->hub_no = hub_no; new_instance_ptr->port_no = port_no; new_instance_ptr->level = level; new_instance_ptr->cfg_value = 0; /* We don't know yet what the device's default configuration is */ new_instance_ptr->attached = (uint8_t)TRUE; new_instance_ptr->pre_detached = (uint8_t)FALSE; //printf("l1\n"); USB_Host_lock(); //printf("l2\n"); dev_instance_ptr = usb_host_ptr->device_list_ptr; while (dev_instance_ptr != NULL) { if ((dev_instance_ptr->hub_no == hub_no) && (dev_instance_ptr->port_no == port_no)) { USB_Host_unlock(); OS_Mem_free((void*)new_instance_ptr); printf("invalidate attach\n"); *handle_ptr = NULL; return USBERR_ERROR; } else { dev_instance_ptr = dev_instance_ptr->next; } } //printf("l3\n"); /* Find unused address from 1 - 127 for this host */ dev_instance_ptr = usb_host_ptr->device_list_ptr; if ((dev_instance_ptr == NULL) || (dev_instance_ptr->address != 1)) { /* Insert at the beginning of list */ new_instance_ptr->target_address = 1; new_instance_ptr->next = dev_instance_ptr; usb_host_ptr->device_list_ptr = new_instance_ptr; } else { dev_instance_prev_ptr = dev_instance_ptr; /* Searching for a 'hole' in devices instance adresses */ while (dev_instance_ptr->target_address <= (dev_instance_prev_ptr->target_address + 1)) { new_instance_ptr->target_address = dev_instance_ptr->target_address; dev_instance_prev_ptr = dev_instance_ptr; dev_instance_ptr = dev_instance_ptr->next; if (dev_instance_ptr == NULL) break; } /* EndWhile */ if (new_instance_ptr->target_address >= 127) { /* If all 127 addresses used up, delete instance & bail out */ USB_Host_unlock(); OS_Mem_free((void*)new_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device out of addresses"); #endif printf("no valid address for the device\n"); *handle_ptr = NULL; return USB_log_error(__FILE__,__LINE__, USBERR_ADDRESS_ALLOC_FAILED); } /* EndIf */ new_instance_ptr->target_address++; new_instance_ptr->next = dev_instance_ptr; dev_instance_prev_ptr->next = new_instance_ptr; }; //printf("l4\n"); USB_Host_unlock(); /*-----------------------------------------------------------** ** Open control pipe, get first 8 bytes of device descriptor ** ** The host_ch9 routine internally sets the callback to ** ** usb_host_cntrl_transaction_done (in usb_host_ch9.c) ** ** where the action resumes on completion of the get. ** **-----------------------------------------------------------*/ pipe_init.endpoint_number = 0; pipe_init.direction = 0; pipe_init.pipetype = USB_CONTROL_PIPE; pipe_init.max_packet_size = 64; pipe_init.interval = 0; pipe_init.flags = 0; pipe_init.dev_instance = new_instance_ptr; pipe_init.nak_count = USBCFG_HOST_DEFAULT_MAX_NAK_COUNT; if (USB_OK != usb_host_open_pipe(new_instance_ptr->host, &new_instance_ptr->control_pipe, &pipe_init)) { OS_Mem_free((void*)new_instance_ptr); *handle_ptr = NULL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device open pipe failed"); #endif printf("can't open control pipe\n"); return USB_log_error(__FILE__,__LINE__, USBERR_PIPE_OPENED_FAILED); } /* Endif */ /* Set state to enter after transaction completion */ new_instance_ptr->state = DEVSTATE_DEVDESC8; status = _usb_host_ch9_get_descriptor((usb_device_instance_handle)new_instance_ptr, USB_DESC_TYPE_DEV << 8, 0, 8, (uint8_t *)&new_instance_ptr->dev_descriptor); if (status != USB_OK) { new_instance_ptr->state = DEVSTATE_INITIAL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device FAILED"); #endif printf("get descriptor error\n"); *handle_ptr = (usb_device_instance_handle)new_instance_ptr; return USB_log_error(__FILE__,__LINE__, USBERR_NO_DESCRIPTOR); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device SUCCESSFUL"); #endif *handle_ptr = (usb_device_instance_handle)new_instance_ptr; //printf("attach done\n"); return USB_OK; } /* 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_otg_init * Returned Value : initialization message * Comments : Initializes OTG stack * * *END*----------------------------------------------------------------------*/ usb_status usb_otg_init ( /* [IN] the USB device controller to initialize */ uint8_t controller_id, /*[IN] address of the OTG initialization structure */ otg_int_struct_t * init_struct_ptr, /* [IN] the USB otg board init handle */ otg_board_init board_init_callback, /* [OUT] the USB host handle */ usb_otg_handle * handle ) { usb_status error = USB_OK; const usb_otg_api_functions_struct_t * otg_api = NULL; usb_otg_state_struct_t * usb_otg_ptr = NULL; if ((init_struct_ptr == NULL) || (handle == NULL)) { #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("usb_otg_init invalid parameters"); #endif return USBERR_ERROR; } _usb_otg_get_api(controller_id, &otg_api); if (otg_api == NULL) { return USBERR_ERROR; } /* Initialize the USB interface. */ if (otg_api->otg_preinit != NULL) { error = otg_api->otg_preinit((usb_otg_handle *) (&(usb_otg_ptr))); if (error || (usb_otg_ptr == NULL)) { #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("usb_OTG_init preinit failure"); #endif return USBERR_ALLOC; } } g_usb_otg_handle = usb_otg_ptr; usb_otg_ptr->otg_controller_api = otg_api; if( NULL !=board_init_callback ) { error = (uint32_t)board_init_callback(controller_id); } else { error = USB_OK; } if(USB_OK == error) { error = usb_otg_soc_init(controller_id); } if (error != USB_OK) { if (otg_api->otg_shutdown != NULL) { error = otg_api->otg_shutdown(usb_otg_ptr); } #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("_usb_host_init: BSP-specific USB initialization failure"); #endif return USB_log_error(__FILE__, __LINE__, USBERR_UNKNOWN_ERROR); } usb_otg_ptr->init_struct = init_struct_ptr; /* initialize the event used for application signaling and for ISR*/ usb_otg_ptr->otg_app_event = OS_Event_create(0); usb_otg_ptr->otg_isr_event = OS_Event_create(0); usb_otg_ptr->device_state = USB_OTG_DEVSTATE_UNDEFINED; usb_otg_ptr->sub_state = USB_OTG_SM_UNDEFINED; usb_otg_ptr->power_up = TRUE; if (otg_api->otg_init != NULL) { error = otg_api->otg_init(controller_id, usb_otg_ptr); } if (error != USB_OK) { if (otg_api->otg_shutdown != NULL) { error = otg_api->otg_shutdown(usb_otg_ptr); } #if ((defined _OTG_DEBUG_) && (_OTG_DEBUG)) DEBUG_LOG_TRACE ("_usb_host_init: BSP-specific USB initialization failure"); #endif return USB_log_error(__FILE__, __LINE__, USBERR_UNKNOWN_ERROR); } error = _usb_otg_task_create(usb_otg_ptr); if (error != USB_OK) { if (otg_api->otg_shutdown != NULL) { otg_api->otg_shutdown(usb_otg_ptr); } (void) OS_Event_destroy(usb_otg_ptr->otg_app_event); (void) OS_Event_destroy(usb_otg_ptr->otg_isr_event); OS_Mem_free(usb_otg_ptr); usb_otg_ptr = NULL; OS_Unlock(); return error; } *handle = (usb_otg_handle) usb_otg_ptr; return USB_OK; }
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_video_stream_deinit * Returned Value : None * Comments : * This function is called by common class to initialize the class driver. It * is called in response to a select interface call by application * *END*--------------------------------------------------------------------*/ usb_status usb_class_video_stream_deinit ( /* [IN] the class driver handle */ class_handle handle ) { usb_video_stream_struct_t* video_stream_ptr = (usb_video_stream_struct_t*)handle; usb_status status = USB_OK; if (video_stream_ptr == NULL) { #ifdef _DEBUG USB_PRINTF("usb_class_video_stream_deinit fail\n"); #endif return USBERR_ERROR; } if (video_stream_ptr->stream_iso_in_pipe != NULL) { status = usb_host_close_pipe(video_stream_ptr->host_handle, video_stream_ptr->stream_iso_in_pipe); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("error in usb_class_video_stream_deinit to close pipe\n"); #endif } } if (video_stream_ptr->stream_iso_out_pipe != NULL) { status = usb_host_close_pipe(video_stream_ptr->host_handle, video_stream_ptr->stream_iso_out_pipe); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("error in usb_class_video_stream_deinit to close pipe\n"); #endif } } if (video_stream_ptr->stream_bulk_in_pipe != NULL) { status = usb_host_close_pipe(video_stream_ptr->host_handle, video_stream_ptr->stream_bulk_in_pipe); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("error in usb_class_video_stream_deinit to close pipe\n"); #endif } } if (video_stream_ptr->stream_bulk_out_pipe != NULL) { status = usb_host_close_pipe(video_stream_ptr->host_handle, video_stream_ptr->stream_bulk_out_pipe); if (status != USB_OK) { #ifdef _DEBUG USB_PRINTF("error in usb_class_video_stream_deinit to close pipe\n"); #endif } } OS_Mem_free(video_stream_ptr->altrnate_if_ep_descriptor_list); OS_Mem_free(handle); //USB_PRINTF("Video class driver de-initialized\n"); return USB_OK; } /* Endbody */
static usb_status usb_class_video_fill_endpoint_descriptor(usb_video_stream_struct_t* video_stream_ptr,uint8_t if_alternate) { usb_device_interface_struct_t* pDeviceIntf = NULL; descriptor_union_t ptr1; descriptor_union_t ptr2; usb_device_ep_struct_t * pEndpoint = NULL; usb_status ret = USB_OK; uint8_t ep_num = 0; /*--------------------------------------------------------** ** If descriptor type is Configuration, the pointer is ** ** found in ptr1. Other types of descriptor need ** ** to be found by stepping through the config one ** ** descriptor at a time. ** ** To prevent parsing past the config buffer, ptr2 is ** ** set to the starting address plus its total size. ** **--------------------------------------------------------*/ pDeviceIntf = video_stream_ptr->stream_interface_ptr; ptr1.pntr = pDeviceIntf->interfaceEx; ptr2.word = ptr1.word + pDeviceIntf->interfaceExlength; while (ptr1.word < ptr2.word) { /* the first interface descriptor found */ if (ptr1.common->bDescriptorType == USB_DESC_TYPE_IF) { if (ptr1.intf->bAlternateSetting == if_alternate) { if (ptr1.intf->bNumEndpoints > USBCFG_HOST_MAX_EP_PER_INTERFACE) { USB_PRINTF("too many endpoints in one interface, please increase the USBCFG_HOST_MAX_EP_PER_INTERFACE value\n"); ret = USBERR_ERROR; break; } if (ptr1.intf->bNumEndpoints > 0) { video_stream_ptr->altrnate_if_ep_num = ptr1.intf->bNumEndpoints; } else { return USB_OK; } if(video_stream_ptr->altrnate_if_ep_descriptor_list) { OS_Mem_free(video_stream_ptr->altrnate_if_ep_descriptor_list); } video_stream_ptr->altrnate_if_ep_descriptor_list = (usb_device_ep_struct_t*)OS_Mem_alloc_zero(video_stream_ptr->altrnate_if_ep_num * sizeof(usb_device_ep_struct_t)); ptr1.word += ptr1.common->bLength; while (ptr1.word < ptr2.word) { if (ptr1.common->bDescriptorType != USB_DESC_TYPE_EP) { ptr1.word += ptr1.common->bLength; } else { break; } } /* now the ptr1 should point to endpoint descriptor */ if (ptr1.common->bDescriptorType != USB_DESC_TYPE_EP) { USB_PRINTF("interface descriptor error\n"); ret = USBERR_ERROR; break; } for (ep_num = 0; ep_num < video_stream_ptr->altrnate_if_ep_num; ep_num++) { if ((ptr1.ndpt->bDescriptorType != USB_DESC_TYPE_EP) || (ptr1.word >= ptr2.word)) { USB_PRINTF("endpoint descriptor error\n"); ret = USBERR_ERROR; break; } pEndpoint = &video_stream_ptr->altrnate_if_ep_descriptor_list[ep_num]; pEndpoint->lpEndpointDesc = ptr1.ndpt; ptr1.word += ptr1.common->bLength; while (ptr1.word < ptr2.word) { if (ptr1.common->bDescriptorType != USB_DESC_TYPE_EP) { ptr1.word += ptr1.common->bLength; } else { break; } } } if (ret != USB_OK) { break; } } else { ptr1.word += ptr1.common->bLength; } } else { ptr1.word += ptr1.common->bLength; } } return ret; }