/*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 (uchar_ptr, cfig_ptr) * is used to parse this buffer in various ways. * *END*--------------------------------------------------------------------*/ static void usb_host_cntrl_transaction_done ( /* [IN] the pipe handle */ _usb_pipe_handle handle, /* [IN] The user parameter */ pointer user_parm, /* [IN] the buffer */ uchar_ptr buffer, /* [IN] The length of the transfer */ uint_32 length, /* [IN] status of the transfer */ uint_32 status ) { /* Body */ USB_HOST_STATE_STRUCT_PTR usb_host_ptr; PIPE_DESCRIPTOR_STRUCT_PTR pipe_ptr = (PIPE_DESCRIPTOR_STRUCT_PTR)handle; DEV_INSTANCE_PTR dev_inst_ptr = (DEV_INSTANCE_PTR)pipe_ptr->DEV_INSTANCE; DESCRIPTOR_UNION desc; pointer temp = NULL; uint_32 config_size; usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)dev_inst_ptr->host; /*----------------------------------------------------** ** Enumeration state machine -- cases are named after ** ** the just-completed transactions. ** **----------------------------------------------------*/ switch (dev_inst_ptr->state) { case DEVSTATE_INITIAL: /* initial device 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 */ pipe_ptr->MAX_PACKET_SIZE = 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) { dev_inst_ptr->state = DEVSTATE_INITIAL; 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((pointer)dev_inst_ptr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_ADDR_SET: /* address set */ pipe_ptr->DEVICE_ADDRESS = dev_inst_ptr->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) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } dev_inst_ptr->state = DEVSTATE_DEV_DESC; /* Now get the full descriptor */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, USB_DESC_LEN_DEV, (uchar_ptr)&dev_inst_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; 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; dev_inst_ptr->state = DEVSTATE_GET_CFG9; status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, sizeof(dev_inst_ptr->buffer), desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_GET_CFG9: /* Read 9 bytes of config descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; /* Now select the configuration as specified in the ** descriptor */ desc.cfig = (CONFIGURATION_DESCRIPTOR_PTR)dev_inst_ptr->buffer; config_size = utoh16(desc.cfig->wTotalLength); desc.pntr = &dev_inst_ptr->buffer; if (USB_OK != usb_dev_list_get_memory(dev_inst_ptr, config_size, USB_MEMTYPE_CONFIG, (pointer _PTR_)&desc)) { return; } desc.word += MEM_HEADER_LEN; /* step past header */ dev_inst_ptr->state = DEVSTATE_SET_CFG; #ifdef OTG_BUILD //the device has to be attached directly(no intervening hub between the Host and the B device) if(dev_inst_ptr->next == (DEV_INSTANCE_PTR)NULL) { dev_inst_ptr->state = DEVSTATE_CHK_OTG; } #endif /* We can only read one config descriptor at a time */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, (uint_16)config_size, desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; #ifdef OTG_BUILD case DEVSTATE_CHK_OTG: /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; /* We will always start with config desc so update the search pointer */ config_size = utoh16(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; } /* Endif */ config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } /* EndWhile */ /* Check for an OTG descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; if (config_size && (desc.otg->bDescriptorType == USB_DESC_TYPE_OTG)) { if(_usb_otg_get_otg_attribute( dev_inst_ptr , desc.otg->bmAttributes) == USB_OK ) { if( _usb_otg_set_feature_required(dev_inst_ptr) ) { status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_A_HNP_SUPPORT); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; } else { dev_inst_ptr->state = DEVSTATE_SET_HNP; } break; } } } /* Endif */ /* Fall through */ #endif case DEVSTATE_SET_CFG: /* config descriptor [0..8] */ /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; dev_inst_ptr->state = DEVSTATE_CFG_READ; status = _usb_host_ch9_set_configuration(dev_inst_ptr, desc.cfig->bConfigurationValue); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; #ifdef OTG_BUILD case DEVSTATE_SET_HNP: dev_inst_ptr->state = DEVSTATE_SET_CFG; status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, OTG_B_HNP_ENABLE); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; } else { _usb_otg_a_set_b_hnp_en(dev_inst_ptr, TRUE); } break; #endif case DEVSTATE_CFG_READ: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_APP_CALL; /* Scan the configuration descriptor to find out the total ** number of interfaces available. This will be the upper ** bound for searching through the interface descriptors' ** array */ dev_inst_ptr->num_of_interfaces = 0; /* Point to the memory owned by this device */ desc.pntr = &dev_inst_ptr->memlist->payload; /* We will always start with config desc so update the search pointer */ config_size = utoh16(desc.cfig->wTotalLength); config_size -= desc.cfig->bLength; desc.word += desc.cfig->bLength; while (config_size) { if (desc.intf->bDescriptorType == USB_DESC_TYPE_IF) { /* Found an interface */ dev_inst_ptr->num_of_interfaces++; } /* Endif */ /* EAI - if desc.intf->bLength this while loop never exits!!!! */ if (desc.intf->bLength) { config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } else { /* Not sure what proper error recovery is yet. */ break; } } /* EndWhile */ /* Don't select an interface here. The device driver will ** select the interface */ case DEVSTATE_APP_CALL: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_SET_INTF; if (dev_inst_ptr->new_config != 0) { /* We have just read a new configuration descriptor */ dev_inst_ptr->new_config = 0; usb_hostdev_attach_detach(dev_inst_ptr, USB_CONFIG_EVENT); } else { usb_hostdev_attach_detach(dev_inst_ptr, USB_ATTACH_EVENT); } /* EndIf */ break; case DEVSTATE_SET_INTF: /* Select interface done */ dev_inst_ptr->state = DEVSTATE_ENUM_OK; usb_hostdev_attach_detach(dev_inst_ptr, USB_INTF_EVENT); break; default: dev_inst_ptr->state = DEVSTATE_ENUM_OK; case DEVSTATE_ENUM_OK: /* enumeration complete */ if ((dev_inst_ptr->control_callback != NULL)) dev_inst_ptr->control_callback (handle, user_parm, buffer, length, status); break; } /* EndSwitch */ } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_dev_list_attach_device * 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_dev_list_attach_device ( _usb_host_handle handle, uint_8 speed, uint_8 hub_no, uint_8 port_no ) { /* Body */ USB_STATUS status; DEV_INSTANCE_PTR new_instance_ptr, dev_instance_ptr, dev_instance_prev_ptr; PIPE_INIT_PARAM_STRUCT ctrl_pipe_init_params; USB_HOST_STATE_STRUCT_PTR usb_host_ptr; DEV_INSTANCE_PTR device_root = NULL; #ifdef __USB_OTG__ uint_32 state; #endif #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device attach device"); #endif usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)handle; /* Allocate new device instance */ new_instance_ptr = (DEV_INSTANCE_PTR) USB_mem_alloc_uncached(sizeof(DEV_INSTANCE)); if (new_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device failed to malloc device handle"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_GET_MEMORY_FAILED); } /* EndIf */ _mem_set_type(new_instance_ptr, MEM_TYPE_USB_HOST_STATE_STRUCT); USB_mem_zero(new_instance_ptr, sizeof(DEV_INSTANCE)); new_instance_ptr->host = handle; new_instance_ptr->speed = speed; new_instance_ptr->hub_no = hub_no; new_instance_ptr->port_no = port_no; new_instance_ptr->cfg_value = 0; /* We don't know yet what the device's default configuration is */ USB_lock(); /* 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->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->address <= (dev_instance_prev_ptr->address + 1)) { new_instance_ptr->address = dev_instance_ptr->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->address >= 127) { /* If all 127 addresses used up, delete instance & bail out */ USB_unlock(); USB_mem_free((pointer)new_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device out of addresses"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_ADDRESS_ALLOC_FAILED); } /* EndIf */ new_instance_ptr->address++; new_instance_ptr->next = dev_instance_ptr; dev_instance_prev_ptr->next = new_instance_ptr; }; USB_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. ** **-----------------------------------------------------------*/ ctrl_pipe_init_params = pipe_init_params_prototype; ctrl_pipe_init_params.G.DEV_INSTANCE = new_instance_ptr; ctrl_pipe_init_params.G.PIPETYPE = USB_CONTROL_PIPE; ctrl_pipe_init_params.G.SPEED = new_instance_ptr->speed; ctrl_pipe_init_params.G.HUB_DEVICE_ADDR = hub_no; ctrl_pipe_init_params.G.HUB_PORT_NUM = port_no; #ifdef __USB_OTG__ _usb_otg_get_status((pointer)usb_otg_state_struct_ptr, USB_OTG_STATE, &state); if (state < B_IDLE) { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_BUS_REQ, TRUE); _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_B_CONN, TRUE); } else { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_CONN, TRUE); } /* Endif */ #endif if (USB_OK != _usb_host_open_pipe(new_instance_ptr->host, &ctrl_pipe_init_params, &new_instance_ptr->control_pipe)) { USB_mem_free((pointer)new_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device open pipe failed"); #endif 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, (uchar_ptr)&new_instance_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { new_instance_ptr->state = DEVSTATE_INITIAL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device FAILED"); #endif return USB_log_error(__FILE__,__LINE__, USBERR_NO_DESCRIPTOR); } #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device SUCCESSFUL"); #endif 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_dev_list_attach_device * 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_dev_list_attach_device ( _usb_host_handle handle, uint_8 speed, uint_8 hub_no, uint_8 port_no ) { /* Body */ USB_STATUS status; DEV_INSTANCE_PTR dev_instance_ptr; PIPE_INIT_PARAM_STRUCT ctrl_pipe_init_params; USB_HOST_STATE_STRUCT_PTR usb_host_ptr; DEV_INSTANCE_PTR device_root = NULL; usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)handle; /* Allocate new device instance */ dev_instance_ptr = (DEV_INSTANCE_PTR) USB_mem_alloc_word_aligned(sizeof(DEV_INSTANCE)); if (dev_instance_ptr == NULL) { return USBERR_GET_MEMORY_FAILED; } /* EndIf */ memset(dev_instance_ptr, 0, sizeof(DEV_INSTANCE)); dev_instance_ptr->host = handle; dev_instance_ptr->speed = speed; dev_instance_ptr->hub_no = hub_no; dev_instance_ptr->port_no = port_no; dev_instance_ptr->cfg_value = 0; /* We don't know yet what the ** device's default configuration is */ USB_lock(); /* Insert instance in pushdown list of devices */ dev_instance_ptr->next = (DEV_INSTANCE_PTR)usb_host_ptr->DEVICE_LIST_PTR; /* existing list */ usb_host_ptr->DEVICE_LIST_PTR = (pointer)dev_instance_ptr; /* root = new device */ device_root = dev_instance_ptr; /* Find unused address from 1 - 127 for this host */ device_root->address = 1; do { dev_instance_ptr = device_root->next; /* 2nd device, if any */ while (dev_instance_ptr != NULL) { /* step through list */ if (device_root->address == dev_instance_ptr->address) { device_root->address++; break; } /* EndIf */ dev_instance_ptr = dev_instance_ptr->next; } /* EndWhile */ } while ((dev_instance_ptr != NULL) && (device_root->address <= 127)); dev_instance_ptr = device_root; /* If all 127 addresses used up, delete instance & bail out */ if (dev_instance_ptr->address > 127) { usb_host_ptr->DEVICE_LIST_PTR = (pointer)\ dev_instance_ptr->next; /* pop off list */ USB_unlock(); USB_mem_free((pointer)dev_instance_ptr); return USBERR_ADDRESS_ALLOC_FAILED; } /* EndIf */ USB_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. ** **-----------------------------------------------------------*/ ctrl_pipe_init_params = pipe_init_params_prototype; ctrl_pipe_init_params.DEV_INSTANCE = dev_instance_ptr; ctrl_pipe_init_params.PIPETYPE = USB_CONTROL_PIPE; ctrl_pipe_init_params.SPEED = dev_instance_ptr->speed; if (USB_OK != _usb_host_open_pipe(dev_instance_ptr->host, &ctrl_pipe_init_params, &dev_instance_ptr->control_pipe)) { USB_mem_free((pointer)dev_instance_ptr); return USBERR_PIPE_OPENED_FAILED; } /* Endif */ /* Set state to enter after transaction completion */ dev_instance_ptr->state = DEVSTATE_DEVDESC8; status = _usb_host_ch9_get_descriptor((pointer)dev_instance_ptr, USB_DESC_TYPE_DEV << 8, 0, 8, (uchar_ptr)&dev_instance_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_instance_ptr->state = DEVSTATE_INITIAL; return USBERR_NO_DESCRIPTOR; } 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 (uchar_ptr, cfig_ptr) * is used to parse this buffer in various ways. * *END*--------------------------------------------------------------------*/ static void usb_host_cntrl_transaction_done ( /* [IN] the pipe handle */ _usb_pipe_handle handle, /* [IN] The user parameter */ pointer user_parm, /* [IN] the buffer */ uchar_ptr buffer, /* [IN] The length of the transfer */ uint_32 length, /* [IN] status of the transfer */ uint_32 status ) { /* Body */ USB_HOST_STATE_STRUCT_PTR usb_host_ptr; PIPE_DESCRIPTOR_STRUCT_PTR pipe_ptr = (PIPE_DESCRIPTOR_STRUCT_PTR)handle; DEV_INSTANCE_PTR dev_inst_ptr = (DEV_INSTANCE_PTR)pipe_ptr->DEV_INSTANCE; DESCRIPTOR_UNION desc; int_32 config_size; DEV_MEMORY_PTR dev_mem; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_cntrl_transaction_done"); #endif usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)dev_inst_ptr->host; switch (status) { case USB_OK: dev_inst_ptr->ctrl_retries = USBCFG_CTRL_RETRY; break; case USBERR_TR_FAILED: if (buffer != NULL) { dev_inst_ptr->ctrl_retries--; if (dev_inst_ptr->ctrl_retries) { if (dev_inst_ptr->state == DEVSTATE_DEVDESC8) { /* dont jump to DEVSTATE_INITIAL state, get descriptor instead */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, 8, (uchar_ptr)buffer); return; } else { dev_inst_ptr->state--; /* back to previous enum state */ status = USB_OK; _time_delay(100); } } } else dev_inst_ptr->state = DEVSTATE_INITIAL; break; case USBERR_ENDPOINT_STALLED: dev_inst_ptr->ctrl_retries--; if (dev_inst_ptr->ctrl_retries) { status = _usb_host_ch9_clear_feature((pointer)dev_inst_ptr, REQ_TYPE_ENDPOINT, 0, ENDPOINT_HALT); if (status == USB_OK) _time_delay(100); } break; default: dev_inst_ptr->state = DEVSTATE_INITIAL; 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 */ pipe_ptr->MAX_PACKET_SIZE = 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) { dev_inst_ptr->state = DEVSTATE_INITIAL; 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((pointer)dev_inst_ptr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_ADDR_SET: /* address set */ pipe_ptr->DEVICE_ADDRESS = dev_inst_ptr->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) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } dev_inst_ptr->state = DEVSTATE_DEV_DESC; /* Now get the full descriptor */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_DEV << 8, 0, USB_DESC_LEN_DEV, (uchar_ptr)&dev_inst_ptr->dev_descriptor); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; 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; dev_inst_ptr->state = DEVSTATE_GET_CFG9; status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, sizeof(dev_inst_ptr->buffer), desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_GET_CFG9: /* Read 9 bytes of config descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; /* Now select the configuration as specified in the ** descriptor */ desc.cfig = (CONFIGURATION_DESCRIPTOR_PTR)dev_inst_ptr->buffer; config_size = SHORT_LE_TO_HOST(*(uint_16*)desc.cfig->wTotalLength); desc.pntr = &dev_inst_ptr->buffer; if (USB_OK != usb_dev_list_get_mem(dev_inst_ptr, config_size, USB_MEMTYPE_CONFIG, 1, &dev_mem)) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_cntrl_transaction_done"); #endif return; } /* Move the pointer to the aligned payload */ desc.pntr = dev_mem->payload.data + dev_mem->offset; #ifdef __USB_OTG__ dev_inst_ptr->state = DEVSTATE_CHK_OTG; #else dev_inst_ptr->state = DEVSTATE_SET_CFG; #endif /* We can only read one config descriptor at a time */ status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr, USB_DESC_TYPE_CFG << 8, 0, (uint_16)config_size, desc.bufr); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_CHK_OTG: /* Point to the memory owned by this device */ /* FIXME: it is presumed that memlist points to the config descriptor */ desc.pntr = dev_inst_ptr->memlist->payload.data + dev_inst_ptr->memlist->offset; /* We will always start with config desc so update the search pointer */ config_size = SHORT_LE_TO_HOST(*(uint_16*)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; } /* Endif */ config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } /* EndWhile */ /* Check for an OTG descriptor */ dev_inst_ptr->state = DEVSTATE_SET_CFG; if (config_size && desc.otg->bDescriptorType == USB_DESC_TYPE_OTG && (desc.otg->bmAttributes & OTG_HNP_SUPPORT)) { status = _usb_host_ch9_set_feature(dev_inst_ptr, 0, 0, 4); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } else { break; } } /* Endif */ /* Fall through */ case DEVSTATE_SET_CFG: /* config descriptor [0..8] */ /* Point to the memory owned by this device */ /* FIXME: it is presumed that memlist points to the config descriptor */ desc.pntr = dev_inst_ptr->memlist->payload.data + dev_inst_ptr->memlist->offset; dev_inst_ptr->state = DEVSTATE_CFG_READ; status = _usb_host_ch9_set_configuration(dev_inst_ptr, desc.cfig->bConfigurationValue); if (status != USB_STATUS_TRANSFER_QUEUED) { dev_inst_ptr->state = DEVSTATE_INITIAL; break; } break; case DEVSTATE_CFG_READ: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_APP_CALL; /* Scan the configuration descriptor to find out the total ** number of interfaces available. This will be the upper ** bound for searching through the interface descriptors' ** array */ dev_inst_ptr->num_of_interfaces = 0; /* Point to the memory owned by this device */ /* FIXME: it is presumed that memlist points to the config descriptor */ desc.pntr = dev_inst_ptr->memlist->payload.data + dev_inst_ptr->memlist->offset; /* We will always start with config desc so update the search pointer */ config_size = SHORT_LE_TO_HOST(*(uint_16*)desc.cfig->wTotalLength); config_size -= desc.cfig->bLength; desc.word += desc.cfig->bLength; while (config_size > 0) { if (desc.intf->bDescriptorType == USB_DESC_TYPE_IF) { /* Found an interface */ dev_inst_ptr->num_of_interfaces++; } /* Endif */ if (desc.intf->bLength) { config_size -= desc.intf->bLength; desc.word += desc.intf->bLength; } else { /* Zero-sized interface found */ status = USBERR_INVALID_CFIG_NUM; break; } } /* EndWhile */ if (config_size < 0) { /* Error: we have not read the configuration descriptor properly, ** some part is missing. Symptom: there is not config descriptor ** info left for latest descriptor. */ status = USBERR_INVALID_CFIG_NUM; } if (status == USBERR_INVALID_CFIG_NUM) { /* TODO: Remove config descriptor from memlist and try to re-read. */ break; } /* Don't select an interface here. The device driver will ** select the interface */ case DEVSTATE_APP_CALL: /* full config desc. read in */ dev_inst_ptr->state = DEVSTATE_SET_INTF; if (dev_inst_ptr->new_config != 0) { /* We have just read a new configuration descriptor */ dev_inst_ptr->new_config = 0; usb_hostdev_attach_detach(dev_inst_ptr, USB_CONFIG_EVENT); } else { usb_hostdev_attach_detach(dev_inst_ptr, USB_ATTACH_EVENT); } /* EndIf */ break; case DEVSTATE_SET_INTF: /* Select interface done */ dev_inst_ptr->state = DEVSTATE_ENUM_OK; usb_hostdev_attach_detach(dev_inst_ptr, USB_INTF_EVENT); break; default: dev_inst_ptr->state = DEVSTATE_ENUM_OK; case DEVSTATE_ENUM_OK: /* enumeration complete */ if ((dev_inst_ptr->control_callback != NULL)) dev_inst_ptr->control_callback (handle, user_parm, buffer, length, status); break; } /* EndSwitch */ #ifdef _HOST_DEBUG_ if (dev_inst_ptr->state == DEVSTATE_INITIAL) { DEBUG_LOG_TRACE("usb_host_cntrl_transaction_done FAILED"); } else { DEBUG_LOG_TRACE("usb_host_cntrl_transaction_done SUCCESSFUL"); } #endif } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_dev_list_attach_device * Returned Value : * Comments : * This function will be called when attach interrupt happens, to * add onto the device list and do common initialization. * *END*--------------------------------------------------------------------*/ void usb_dev_list_attach_device ( _usb_host_handle handle, uint_8 speed, uint_8 hub_no, uint_8 port_no ) { /* Body */ DEV_INSTANCE_PTR dev_instance_ptr; PIPE_INIT_PARAM_STRUCT ctrl_pipe_init_params; USB_HOST_STATE_STRUCT_PTR usb_host_ptr; DEV_INSTANCE_PTR device_root = NULL; // clean warning uint_32 state; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device attach device"); DEBUGMSG(USB_DBG_LEVEL, ("usb_dev_list_attach_device attach device\n")); #endif //DEBUGMSG(1,("d")); //DEBUGMSG(TTC_DBG_LEVEL,("usb_dev_list_attach_device attach device\r\n")); usb_host_ptr = (USB_HOST_STATE_STRUCT_PTR)handle; /* Allocate new device instance */ dev_instance_ptr = (DEV_INSTANCE_PTR)\ USB_Uncached_memalloc(sizeof(DEV_INSTANCE)); if (dev_instance_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device failed to malloc device handle"); #endif //DEBUGMSG(TTC_DBG_LEVEL,("usb_dev_list_attach_device failed to malloc device handle\r\n")); return; } /* EndIf */ USB_memzero(dev_instance_ptr, sizeof(DEV_INSTANCE)); dev_instance_ptr->host = handle; dev_instance_ptr->speed = speed; dev_instance_ptr->hub_no = hub_no; dev_instance_ptr->port_no = port_no; dev_instance_ptr->cfg_value = 0; /* We don't know yet what the ** device's default configuration is */ USB_lock(); /* Insert instance in pushdown list of devices */ dev_instance_ptr->next = usb_host_ptr->DEVICE_LIST_PTR; /* existing list */ usb_host_ptr->DEVICE_LIST_PTR = (pointer)dev_instance_ptr; /* root = new device */ device_root = dev_instance_ptr; /* Find unused address from 1 - 127 for this host */ device_root->address = 1; do { dev_instance_ptr = device_root->next; /* 2nd device, if any */ while (dev_instance_ptr != NULL) { /* step through list */ if (device_root->address == dev_instance_ptr->address) { device_root->address++; break; } /* EndIf */ dev_instance_ptr = dev_instance_ptr->next; } /* EndWhile */ } while ((dev_instance_ptr != NULL) && (device_root->address <= 127)); dev_instance_ptr = device_root; /* If all 127 addresses used up, delete instance & bail out */ if (dev_instance_ptr->address > 127) { usb_host_ptr->DEVICE_LIST_PTR = (pointer)\ dev_instance_ptr->next; /* pop off list */ USB_unlock(); USB_memfree((pointer)dev_instance_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device out of addresses"); #endif //DEBUGMSG(TTC_DBG_LEVEL,("usb_dev_list_attach_device out of addresses\r\n")); return; } /* EndIf */ USB_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. ** **-----------------------------------------------------------*/ ctrl_pipe_init_params = pipe_init_params_prototype; ctrl_pipe_init_params.DEV_INSTANCE = dev_instance_ptr; ctrl_pipe_init_params.PIPETYPE = USB_CONTROL_PIPE; ctrl_pipe_init_params.SPEED = dev_instance_ptr->speed; #ifdef __USB_OTG__ _usb_otg_get_status((pointer)usb_otg_state_struct_ptr, USB_OTG_STATE, &state); if (state < B_IDLE) { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_BUS_REQ, TRUE); _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_B_CONN, TRUE); } else { _usb_otg_set_status((pointer)usb_otg_state_struct_ptr, USB_OTG_A_CONN, TRUE); } /* Endif */ #endif if (USB_OK != _usb_host_open_pipe(dev_instance_ptr->host, &ctrl_pipe_init_params, &dev_instance_ptr->control_pipe)) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device open pipe failed"); DEBUGMSG(USB_DBG_LEVEL, ("usb_dev_list_attach_device attach device open pipe failed\n")); #endif //DEBUGMSG(TTC_DBG_LEVEL,("usb_dev_list_attach_device open pipe failed\r\n")); return; } /* Endif */ /* Set state to enter after transaction completion */ dev_instance_ptr->state = DEVSTATE_DEVDESC8; _usb_host_ch9_get_descriptor((pointer)dev_instance_ptr, DESCTYPE_DEVICE<<8, 0, 8, (uchar_ptr)&dev_instance_ptr->dev_descriptor); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_dev_list_attach_device SUCCESSFUL"); DEBUGMSG(USB_DBG_LEVEL, ("usb_dev_list_attach_device SUCCESSFUL\n")); #endif //DEBUGMSG(TTC_DBG_LEVEL,("usb_dev_list_attach_device SUCCESSFUL\r\n")); } /* EndBody */