/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_host_hub_device_sm * Returned Value : None * Comments : * called when a hub changes state; sm = state machine *END*--------------------------------------------------------------------*/ static void usb_host_hub_device_sm ( /* [IN] structure with USB pipe information on the interface */ PIPE_STRUCT_PTR pipe, /* [IN] parameters */ pointer param, /* [IN] buffer of data from IN stage */ pointer buffer, /* [IN] length of data from IN stage */ uint_32 len, /* [IN] status of transaction */ USB_STATUS status ) { /* Body */ register HUB_DEVICE_STRUCT_PTR hub_instance = (HUB_DEVICE_STRUCT_PTR) param; _mqx_int i; switch (hub_instance->STATE) { case HUB_GET_DESCRIPTOR_TINY_PROCESS: /* here we get number of ports from USB data */ hub_instance->HUB_PORT_NR = ((HUB_DESCRIPTOR_STRUCT_PTR) buffer)->BNRPORTS; hub_instance->STATE = HUB_GET_DESCRIPTOR_PROCESS; usb_class_hub_get_descriptor((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, 7 + hub_instance->HUB_PORT_NR / 8 + 1); break; case HUB_GET_DESCRIPTOR_PROCESS: { /* here, we get information from the hub and fill info in hub_instance */ HUB_DESCRIPTOR_STRUCT_PTR hub_desc = (HUB_DESCRIPTOR_STRUCT_PTR) buffer; hub_instance->HUB_PORTS = USB_mem_alloc_zero(hub_instance->HUB_PORT_NR * sizeof(HUB_PORT_STRUCT)); for (i = 0; i < hub_instance->HUB_PORT_NR; i++) { /* get REMOVABLE bit from the desriptor for appropriate installed port */ (hub_instance->HUB_PORTS + i)->APP_STATUS = hub_desc->DEVICEREMOVABLE[(i + 1) / 8] & (0x01 << ((i + 1) % 8)) ? HUB_PORT_REMOVABLE : 0; } } /* pass fluently to HUB_SET_PORT_FEATURE_PROCESS */ hub_instance->STATE = HUB_SET_PORT_FEATURE_PROCESS; hub_instance->port_iterator = 0; case HUB_SET_PORT_FEATURE_PROCESS: // if (hub_instance->port_iterator) /* register, that the port is now powered */ // hub_instance->HUB_PORTS[hub_instance->port_iterator - 1].POWERED = 1; if (hub_instance->port_iterator < hub_instance->HUB_PORT_NR) { usb_class_hub_set_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, ++hub_instance->port_iterator, PORT_POWER); break; } /* EndIf */ /* else */ /* pass fluently to HUB_CLEAR_PORT_FEATURE_PROCESS */ hub_instance->STATE = HUB_CLEAR_PORT_FEATURE_PROCESS; hub_instance->port_iterator = 0; case HUB_CLEAR_PORT_FEATURE_PROCESS: if (hub_instance->port_iterator < hub_instance->HUB_PORT_NR) { usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, ++hub_instance->port_iterator, C_PORT_CONNECTION); break; } /* EndIf */ /* else */ /* pass fluently to HUB_GET_PORT_STATUS_PROCESS */ hub_instance->STATE = HUB_GET_PORT_STATUS_PROCESS; hub_instance->port_iterator = 0; case HUB_GET_PORT_STATUS_PROCESS: if (hub_instance->port_iterator) /* register the current status of the port, do the conversion LSB -> MSB */ (hub_instance->HUB_PORTS + hub_instance->port_iterator - 1)->STATUS = SHORT_LE_TO_HOST(*(uint_16*)buffer); if (hub_instance->port_iterator < hub_instance->HUB_PORT_NR) { usb_class_hub_get_port_status((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, ++hub_instance->port_iterator, 4); break; } /* EndIf */ /* else */ /* test if device is attached since startup */ for (i = 0; i < hub_instance->HUB_PORT_NR; i++) if ((hub_instance->HUB_PORTS + i)->STATUS & (1 << PORT_CONNECTION)) { /* if some device is attached since startup, then start session */ hub_instance->port_iterator = i; hub_instance->STATE = HUB_NONE; (hub_instance->HUB_PORTS + i)->APP_STATUS |= HUB_PORT_ATTACHED; usb_class_hub_set_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, PORT_RESET); break; } usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; case HUB_RESET_DEVICE_PORT_PROCESS: hub_instance->STATE = HUB_NONE; usb_class_hub_set_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, PORT_RESET); usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; case HUB_ADDRESS_DEVICE_PORT_PROCESS: /* compute speed */ if ((hub_instance->HUB_PORTS + hub_instance->port_iterator)->STATUS & (1 << PORT_HIGH_SPEED)) i = USB_SPEED_HIGH; else if ((hub_instance->HUB_PORTS + hub_instance->port_iterator)->STATUS & (1 << PORT_LOW_SPEED)) i = USB_SPEED_LOW; else i = USB_SPEED_FULL; /* FIXME: accessing intf_handle directly without validation to get its host handle is not good method */ usb_dev_list_attach_device( ((USB_HUB_CLASS_INTF_STRUCT_PTR) hub_instance->CCS.class_intf_handle)->G.host_handle, i, /* port speed */ pipe->DEVICE_ADDRESS, /* hub address */ hub_instance->port_iterator + 1 /* hub port */ ); /* test if there is still device which was not reset */ for (i = 0; i < hub_instance->HUB_PORT_NR; i++) if (((hub_instance->HUB_PORTS + i)->STATUS & (1 << PORT_CONNECTION)) && !((hub_instance->HUB_PORTS + i)->APP_STATUS & HUB_PORT_ATTACHED)) { /* if some device is attached since startup, then start session */ hub_instance->port_iterator = i; hub_instance->STATE = HUB_NONE; (hub_instance->HUB_PORTS + i)->APP_STATUS |= HUB_PORT_ATTACHED; usb_class_hub_set_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, PORT_RESET); break; } usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; case HUB_DETACH_DEVICE_PORT_PROCESS: /* FIXME: accessing intf_handle directly without validation to get its host handle is not good method */ usb_dev_list_detach_device( ((USB_HUB_CLASS_INTF_STRUCT_PTR) hub_instance->CCS.class_intf_handle)->G.host_handle, pipe->DEVICE_ADDRESS, /* hub address */ hub_instance->port_iterator + 1 /* hub port */ ); /* reset the app status */ (hub_instance->HUB_PORTS + hub_instance->port_iterator)->APP_STATUS = 0x00; /* test if there is still device which was not reset */ for (i = 0; i < hub_instance->HUB_PORT_NR; i++) if (((hub_instance->HUB_PORTS + i)->STATUS & (1 << PORT_CONNECTION)) && !((hub_instance->HUB_PORTS + i)->APP_STATUS & HUB_PORT_ATTACHED)) { /* if some device is attached since startup, then start session */ hub_instance->port_iterator = i; hub_instance->STATE = HUB_NONE; (hub_instance->HUB_PORTS + i)->APP_STATUS |= HUB_PORT_ATTACHED; usb_class_hub_set_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, PORT_RESET); break; } usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; case HUB_GET_PORT_STATUS_ASYNC: { uint_32 stat = LONG_LE_TO_HOST(*(uint_32*)buffer); /* register the current status of the port */ (hub_instance->HUB_PORTS + hub_instance->port_iterator)->STATUS = stat; /* let's see what happened */ if ((1 << C_PORT_CONNECTION) & stat) { /* get if a device on port was attached or detached */ if ((hub_instance->HUB_PORTS + hub_instance->port_iterator)->APP_STATUS & HUB_PORT_ATTACHED) { hub_instance->STATE = HUB_DETACH_DEVICE_PORT_PROCESS; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_CONNECTION); } else { hub_instance->STATE = HUB_RESET_DEVICE_PORT_PROCESS; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_CONNECTION); } break; } else if ((1 << C_PORT_RESET) & stat) { hub_instance->STATE = HUB_ADDRESS_DEVICE_PORT_PROCESS; (hub_instance->HUB_PORTS + hub_instance->port_iterator)->APP_STATUS |= HUB_PORT_ATTACHED; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_RESET); break; } else if ((1 << C_PORT_ENABLE) & stat) { /* unexpected event (error), just ignore the port */ hub_instance->STATE = HUB_DETACH_DEVICE_PORT_PROCESS; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_ENABLE); break; } else if ((1 << C_PORT_OVER_CURRENT) & stat) { /* unexpected event (error), just ignore the port */ hub_instance->STATE = HUB_NONE; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_OVER_CURRENT); usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; } else if ((1 << C_PORT_POWER) & stat) { /* unexpected event (error), just ignore the port */ hub_instance->STATE = HUB_NONE; usb_class_hub_clear_port_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, hub_instance->port_iterator + 1, C_PORT_POWER); usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); break; } /* FIXME: handle more events */ break; } case HUB_GET_STATUS_ASYNC: { HUB_STATUS_STRUCT_PTR hub_stat = (HUB_STATUS_STRUCT_PTR) buffer; uint_32 change = SHORT_LE_TO_HOST(hub_stat->WHUBCHANGE); if ((1 << C_HUB_LOCAL_POWER) & change) { hub_instance->STATE = HUB_NONE; usb_class_hub_clear_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, C_HUB_LOCAL_POWER); usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); } else if ((1 << C_HUB_OVER_CURRENT) & change) { hub_instance->STATE = HUB_NONE; usb_class_hub_clear_feature((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_device_sm, (pointer) hub_instance, C_HUB_OVER_CURRENT); usb_class_hub_wait_for_interrupt((CLASS_CALL_STRUCT_PTR) &hub_instance->CCS, (tr_callback) usb_host_hub_int_callback, (pointer) hub_instance, hub_instance->HUB_PORT_NR / 8 + 1); } break; } } /* EndSwitch */ return; } /* EndBody */
static void usb_host_mass_test_storage ( void ) { /* Body */ USB_STATUS status = USB_OK; uint_8 bLun = 0; INQUIRY_DATA_FORMAT inquiry; CAPACITY_LIST capacity_list; #if 0 MODE_SELECT_PARAMETER_LIST md_list; #endif MASS_STORAGE_READ_CAPACITY_CMD_STRUCT_INFO read_capacity; REQ_SENSE_DATA_FORMAT req_sense; FORMAT_UNIT_PARAMETER_BLOCK formatunit = { 0}; _mqx_int block_len; DEVICE_DESCRIPTOR_PTR pdd; CBW_STRUCT_PTR cbw_ptr = pCmd->CBW_PTR; CSW_STRUCT_PTR csw_ptr = pCmd->CSW_PTR; USB_mem_zero(buff_out,0x0F); USB_mem_zero(buff_in,0x400C); USB_mem_zero(pCmd->CSW_PTR,sizeof(CSW_STRUCT)); USB_mem_zero(pCmd->CBW_PTR,sizeof(CBW_STRUCT)); USB_mem_zero(pCmd,sizeof(COMMAND_OBJECT_STRUCT)); pCmd->CBW_PTR = cbw_ptr; pCmd->CSW_PTR = csw_ptr; pCmd->LUN = bLun; pCmd->CALL_PTR = (pointer)&mass_device.class_intf; pCmd->CALLBACK = usb_host_mass_bulk_callback; printf("\n =============START OF A NEW SESSION=================="); if (USB_OK != _usb_hostdev_get_descriptor( mass_device.dev_handle, NULL, USB_DESC_TYPE_DEV, 0, 0, (pointer *) &pdd)) { printf ("\nCould not retrieve device descriptor."); return; } else printf("\nVID = 0x%04x, PID = 0x%04x", SHORT_LE_TO_HOST(*(uint_16*)pdd->idVendor), SHORT_LE_TO_HOST(*(uint_16*)pdd->idProduct)); /* Test the GET MAX LUN command */ printf("\nTesting: GET MAX LUN Command"); fflush(stdout); bCallBack = FALSE; status = usb_class_mass_getmaxlun_bulkonly( (pointer)&mass_device.class_intf, &bLun, usb_host_mass_ctrl_callback); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack) {;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the TEST UNIT READY command */ printf("Testing: TEST UNIT READY Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_test_unit_ready(pCmd); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the INQUIRY command */ printf("Testing: INQUIRY Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_inquiry(pCmd, (uchar_ptr) &inquiry, sizeof(INQUIRY_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the READ FORMAT CAPACITY command */ printf("Testing: READ FORMAT CAPACITIES Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_format_capacity(pCmd, (uchar_ptr)&capacity_list, sizeof(CAPACITY_LIST)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the READ CAPACITY command */ printf("Testing: READ CAPACITY Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_read_capacity(pCmd, (uchar_ptr)&read_capacity, sizeof(MASS_STORAGE_READ_CAPACITY_CMD_STRUCT_INFO)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } block_len = HOST_TO_BE_LONG(* (uint_32 *) &read_capacity.BLENGTH); #if 0 /* Test the MODE SELECT command */ printf("Testing: MODE SELECT Command"); fflush(stdout); bCallBack = FALSE; //md_list. Fill parameters here USB_mem_zero (&md_list, sizeof (MODE_SELECT_PARAMETER_LIST)); md_list.MODE_PARAM_HEADER.BLENGTH[1] = 0x06; status = usb_mass_ufi_mode_select(pCmd, &md_list, 8); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } #endif /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the READ(10) command */ printf("Testing: READ(10) Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_read_10(pCmd, 0, buff_in, block_len, 1); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the MODE SENSE command */ printf("Testing: MODE SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_mode_sense(pCmd, 2, //PC 0x3F, //page code buff_in, (uint_32)0x08); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the PREVENT ALLOW command */ printf("Testing: PREVENT-ALLOW MEDIUM REMOVAL Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_prevent_allow_medium_removal( pCmd, 1 // prevent ); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the VERIFY command */ printf("Testing: VERIFY Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_verify( pCmd, 0x400, // block address 1 //length to be verified ); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the WRITE(10) command */ printf("Testing: WRITE(10) Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_write_10(pCmd, 8, buff_out, block_len, 1); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the REQUEST SENSE command */ printf("Testing: REQUEST SENSE Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_request_sense(pCmd, &req_sense, sizeof(REQ_SENSE_DATA_FORMAT)); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } /* Test the START-STOP UNIT command */ printf("Testing: START-STOP UNIT Command"); fflush(stdout); bCallBack = FALSE; status = usb_mass_ufi_start_stop(pCmd, 0, 1); if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED)) { printf ("\n...ERROR"); return; } else { /* Wait till command comes back */ while (!bCallBack){;} if (!bStatus) { printf("...OK\n"); } else { printf("...Unsupported by device (bStatus=0x%x)\n", bStatus); } } printf("\nTest done!"); fflush(stdout); } /* Endbody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : usb_class_audio_control_get_descriptors * Returned Value : USB_OK * Comments : * This function is hunting for descriptors in the device configuration * and fills back fields if the descriptor was found. * Must be run in locked state and validated USB device or * directly from attach event. *END*--------------------------------------------------------------------*/ USB_STATUS usb_class_audio_control_get_descriptors ( /* [IN] pointer to device instance */ _usb_device_instance_handle dev_handle, /* [IN] pointer to interface descriptor */ _usb_interface_descriptor_handle intf_handle, /* [OUT] pointer to header descriptor */ USB_AUDIO_CTRL_DESC_HEADER_PTR _PTR_ header_desc, /* [OUT] pointer to input terminal descriptor */ USB_AUDIO_CTRL_DESC_IT_PTR _PTR_ it_desc, /* [OUT] pointer to output terminal descriptor */ USB_AUDIO_CTRL_DESC_OT_PTR _PTR_ ot_desc, /* [OUT] pointer to feature unit descriptor */ USB_AUDIO_CTRL_DESC_FU_PTR _PTR_ fu_desc ) { INTERFACE_DESCRIPTOR_PTR intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle; USB_STATUS status; int_32 i; USB_AUDIO_CTRL_FUNC_DESC_PTR fd; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors"); #endif status = USB_OK; /* collect all interface functional descriptors */ for (i = 0; ; i++) { if (USB_OK != _usb_hostdev_get_descriptor( dev_handle, intf_handle, USB_DESC_TYPE_CS_INTERFACE, /* Functional descriptor for interface */ i, /* Index of descriptor */ intf_ptr->bAlternateSetting, /* Index of interface alternate */ (pointer _PTR_) &fd)) { /* Here we can check capabilities from functional descriptors */ /* But for now, nothing is checked */ if (fu_desc == NULL) status = USBERR_INIT_FAILED; break; } /* Check if this union descriptor describes master for this interface */ switch (fd->header.bDescriptorSubtype) { case USB_DESC_SUBTYPE_AUDIO_CS_HEADER: *header_desc = &fd->header; if (SHORT_LE_TO_HOST(*(uint_16*)((*header_desc)->bcdCDC)) > 0x0110) status = USBERR_INIT_FAILED; break; case USB_DESC_SUBTYPE_AUDIO_CS_IT: *it_desc = &fd->it; break; case USB_DESC_SUBTYPE_AUDIO_CS_OT: *ot_desc = &fd->ot; break; case USB_DESC_SUBTYPE_AUDIO_CS_FU: *fu_desc = &fd->fu; break; } if (status != USB_OK) break; } #ifdef _HOST_DEBUG_ if (!status) DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors, SUCCESSFULL"); else DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors, FAILED"); #endif return status; }
/*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_host_ch9_dev_req * Returned Value : USB_OK, or error status * Comments : * Function to process standard device requests in Chapter 9. * See Table 9-3 p. 250 of USB 2.0 specification. * This code does minimal error checking, on the assumption * that it is called only from wrappers in this file. * It is presumed that this function is called with USB interrupts disabled * *END*--------------------------------------------------------------------*/ static USB_STATUS usb_host_ch9_dev_req ( /* usb device */ _usb_device_instance_handle dev_handle, /* Device Request to send */ USB_SETUP_PTR devreq_ptr, /* buffer to send/receive */ uchar_ptr buff_ptr ) { /* Body */ DEV_INSTANCE_PTR dev_ptr; _usb_pipe_handle pipe_handle; TR_INIT_PARAM_STRUCT tr; USB_STATUS error; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_ch9_dev_req"); #endif /* Verify that device handle is valid */ error = usb_hostdev_validate(dev_handle); if (error != USB_OK) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_ch9_dev_req device not found"); #endif return USB_log_error(__FILE__,__LINE__,USBERR_DEVICE_NOT_FOUND); } /* Endif */ dev_ptr = (DEV_INSTANCE_PTR)dev_handle; pipe_handle = dev_ptr->control_pipe; /* Initialize the TR with TR index and default control callback ** function if there is one registered */ usb_hostdev_tr_init(&tr, dev_ptr->control_callback, dev_ptr->control_callback_param); /* Set buffer length if required */ switch (devreq_ptr->BREQUEST) { case REQ_SET_DESCRIPTOR: tr.TX_BUFFER = buff_ptr; tr.TX_LENGTH = SHORT_LE_TO_HOST(*(uint_16*)devreq_ptr->WLENGTH); break; case REQ_GET_CONFIGURATION: case REQ_GET_DESCRIPTOR: case REQ_GET_INTERFACE: case REQ_GET_STATUS: case REQ_SYNCH_FRAME: tr.RX_BUFFER = buff_ptr; tr.RX_LENGTH = SHORT_LE_TO_HOST(*(uint_16*)devreq_ptr->WLENGTH); break; } /* EndSwitch */ tr.DEV_REQ_PTR = (uchar_ptr)(devreq_ptr); if ((dev_ptr->state < DEVSTATE_ENUM_OK) || (tr.CALLBACK == NULL)) { tr.CALLBACK = usb_host_cntrl_transaction_done; tr.CALLBACK_PARAM = NULL; } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_host_ch9_dev_req SUCCESSFUL"); #endif error = _usb_host_send_setup(dev_ptr->host, pipe_handle, &tr); return USB_log_error(__FILE__,__LINE__,error); } /* EndBody */
/*FUNCTION*---------------------------------------------------------------- * * Function Name : _usb_hostdev_cntrl_request * Returned Value : USB_OK, or error status * Comments : * Function to process class- or vendor-specific control pipe device * requests. * *END*--------------------------------------------------------------------*/ USB_STATUS _usb_hostdev_cntrl_request ( /* usb device */ _usb_device_instance_handle dev_handle, /* Device Request to send */ USB_SETUP_PTR devreq, /* buffer to send/receive */ uchar_ptr buff_ptr, /* callback upon completion */ tr_callback callback, /* [IN] the parameter to pass back to the callback function */ pointer callback_param ) { /* Body */ DEV_INSTANCE_PTR dev_ptr; _usb_pipe_handle pipe_handle; TR_INIT_PARAM_STRUCT tr; USB_STATUS error = USB_OK; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("_usb_hostdev_cntrl_request"); #endif /* Verify that device handle is valid */ USB_lock(); error = usb_hostdev_validate(dev_handle); if (error != USB_OK) { USB_unlock(); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("_usb_hostdev_cntrl_request, invalid device handle"); #endif return USB_log_error(__FILE__,__LINE__,USBERR_DEVICE_NOT_FOUND); } /* Endif */ dev_ptr = (DEV_INSTANCE_PTR)dev_handle; if (dev_ptr->state < DEVSTATE_ENUM_OK) { USB_unlock(); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("_usb_hostdev_cntrl_request, no device found"); #endif return USB_log_error(__FILE__,__LINE__,USBERR_DEVICE_NOT_FOUND); } /* Endif */ pipe_handle = dev_ptr->control_pipe; usb_hostdev_tr_init(&tr, callback, callback_param); /* Set TR buffer length as required */ if ((REQ_TYPE_IN & devreq->BMREQUESTTYPE) != 0) { tr.RX_BUFFER = buff_ptr; tr.RX_LENGTH = SHORT_LE_TO_HOST(*(uint_16*)devreq->WLENGTH); } else { tr.TX_BUFFER = buff_ptr; tr.TX_LENGTH = SHORT_LE_TO_HOST(*(uint_16*)devreq->WLENGTH); } /* EndIf */ tr.DEV_REQ_PTR = (uchar_ptr)devreq; error = _usb_host_send_setup(dev_ptr->host, pipe_handle, &tr); USB_unlock(); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("_usb_hostdev_cntrl_request,SUCCESSFUL"); #endif return USB_log_error(__FILE__,__LINE__,error); } /* EndBody */