/** * Answer To Reset (ATR) * \param pAtr ATR buffer * \param pLength Pointer for store the ATR length */ void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength ) { uint32_t i; uint32_t j; uint32_t y; *pLength = 0; /* Read ATR TS */ ISO7816_GetChar(&pAtr[0]); /* Read ATR T0 */ ISO7816_GetChar(&pAtr[1]); y = pAtr[1] & 0xF0; i = 2; /* Read ATR Ti */ while (y) { if (y & 0x10) { /* TA[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x20) { /* TB[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x40) { /* TC[i] */ ISO7816_GetChar(&pAtr[i++]); } if (y & 0x80) { /* TD[i] */ ISO7816_GetChar(&pAtr[i]); y = pAtr[i++] & 0xF0; } else { y = 0; } } /* Historical Bytes */ y = pAtr[1] & 0x0F; for( j=0; j < y; j++ ) { ISO7816_GetChar(&pAtr[i++]); } TRACE_DEBUG_WP("Length = %d", i); TRACE_DEBUG_WP("ATR = "); for (j=0; j < i; j++) { TRACE_DEBUG_WP("%02x ", pAtr[j]); } TRACE_DEBUG_WP("\n\r"); *pLength = i; }
/** * \brief Initialize a list of OV registers. * The list of registers is terminated by the pair of values * \param pTwid TWI interface * \param pReglist Register list to be written * \return 0 if no error; otherwise TWID_ERROR_BUSY */ uint32_t ov_write_regs8(Twid *pTwid, const struct ov_reg* pReglist) { uint32_t err; uint32_t size=0; const struct ov_reg *pNext = pReglist; volatile uint32_t delay; TRACE_DEBUG("ov_write_regs:"); while (!((pNext->reg == OV_REG_TERM) && (pNext->val == OV_VAL_TERM))) { err = ov_write_reg8(pTwid, pNext->reg, pNext->val); size++; for(delay=0;delay<=10000;delay++); if (err == TWID_ERROR_BUSY) { TRACE_ERROR("ov_write_regs: TWI ERROR\n\r"); return err; } TRACE_DEBUG("(0x%02x,0x%02x) \n\r", pNext->reg,pNext->val); pNext++; } TRACE_DEBUG_WP("\n\r"); return 0; }
/** * Reuse first used/released buffer with new buffer address and size to be used * in transfer again. Only valid when frame list is ringed. Can be used for * both read & write. * \param bEndpoint Endpoint number. * \param pNewBuffer Pointer to new buffer with data to send (0 to keep last). * \param wNewSize Size of the data buffer */ uint8_t USBD_MblReuse( uint8_t bEndpoint, uint8_t *pNewBuffer, uint16_t wNewSize ) { Endpoint *pEndpoint = &(endpoints[bEndpoint]); MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer); USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->freedBuffer]); TRACE_DEBUG_WP("MblReuse(%d), st%x, circ%d\n\r", bEndpoint, pEndpoint->state, pTransfer->circList); /* Only for Multi-buffer-circle list */ if (bEndpoint != 0 && (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM || pEndpoint->state == UDP_ENDPOINT_SENDINGM) && pTransfer->circList) { } else { return USBD_STATUS_WRONG_STATE; } /* Check if there is freed buffer */ if (pTransfer->freedBuffer == pTransfer->currBuffer && !pTransfer->allUsed) { return USBD_STATUS_LOCKED; } /* Update transfer information */ if ((++ pTransfer->freedBuffer) == pTransfer->listSize) pTransfer->freedBuffer = 0; if (pNewBuffer) { pBi->pBuffer = pNewBuffer; pBi->size = wNewSize; } pBi->buffered = 0; pBi->transferred = 0; pBi->remaining = pBi->size; /* At least one buffer is not processed */ pTransfer->allUsed = 0; return USBD_STATUS_SUCCESS; }
/** * Sends data frames through a USB endpoint. Sets up the transfer descriptor * list, writes one or two data payloads (depending on the number of FIFO bank * for the endpoint) and then starts the actual transfer. The operation is * complete when all the data has been sent. * * *If the size of the frame is greater than the size of the endpoint * (or twice the size if the endpoint has two FIFO banks), then the buffer * must be kept allocated until the frame is finished*. This means that * it is not possible to declare it on the stack (i.e. as a local variable * of a function which returns after starting a transfer). * * \param bEndpoint Endpoint number. * \param pMbl Pointer to a frame (USBDTransferBuffer) list that describes * the buffer list to send. * \param wListSize Size of the frame list. * \param bCircList Circle the list. * \param wStartNdx For circled list only, the first buffer index to transfer. * \param fCallback Optional callback function to invoke when the transfer is * complete. * \param pArgument Optional argument to the callback function. * \return USBD_STATUS_SUCCESS if the transfer has been started; * otherwise, the corresponding error status code. * \see USBDTransferBuffer, MblTransferCallback, USBD_MblReuse */ uint8_t USBD_MblWrite( uint8_t bEndpoint, void *pMbl, uint16_t wListSize, uint8_t bCircList, uint16_t wStartNdx, MblTransferCallback fCallback, void *pArgument ) { Endpoint *pEndpoint = &(endpoints[bEndpoint]); MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer); uint16_t i; /* EP0 is not suitable for Mbl */ if (bEndpoint == 0) { return USBD_STATUS_INVALID_PARAMETER; } /* Check that the endpoint is in Idle state */ if (pEndpoint->state != UDP_ENDPOINT_IDLE) { return USBD_STATUS_LOCKED; } pEndpoint->state = UDP_ENDPOINT_SENDINGM; TRACE_DEBUG_WP("WriteM%d(0x%x,%d) ", bEndpoint, pMbl, wListSize); /* Start from first if not circled list */ if (!bCircList) wStartNdx = 0; /* Setup the transfer descriptor */ pTransfer->pMbl = (USBDTransferBuffer*)pMbl; pTransfer->listSize = wListSize; pTransfer->fCallback = fCallback; pTransfer->pArgument = pArgument; pTransfer->currBuffer = wStartNdx; pTransfer->freedBuffer = 0; pTransfer->pLastLoaded = &(((USBDTransferBuffer*)pMbl)[wStartNdx]); pTransfer->circList = bCircList; pTransfer->allUsed = 0; /* Clear all buffer */ for (i = 0; i < wListSize; i ++) { pTransfer->pMbl[i].transferred = 0; pTransfer->pMbl[i].buffered = 0; pTransfer->pMbl[i].remaining = pTransfer->pMbl[i].size; } /* Send the first packet */ while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY); UDP_MblWriteFifo(bEndpoint); SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); /* If double buffering is enabled and there is data remaining, */ /* prepare another packet */ if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->pMbl[pTransfer->currBuffer].remaining > 0)) { UDP_MblWriteFifo(bEndpoint); } /* Enable interrupt on endpoint */ UDP->UDP_IER = 1 << bEndpoint; return USBD_STATUS_SUCCESS; }
//------------------------------------------------------------------------------ /// USB interrupt subroutine /// /// This function is called each time a USB interrupt occurs. /// The following USB DEVICE events are taken in charge: /// - VBus On / Off /// - Start Of Frame /// - Suspend /// - Wake-Up /// - Resume /// - Reset /// - Start of frame /// /// The following USB HOST events are taken in charge: /// - Device connection /// - Device Disconnection /// - Start Of Frame /// - ID pin change /// - SOF (or Keep alive in low speed) sent /// - Wake up on USB line detected /// /// The following USB HOST events are taken in charge: /// - HNP success (Role Exchange) /// - HNP failure (HNP Error) /// /// For each event, the user can launch an action by completing /// the associate define (See conf_usb.h file to add action upon events) /// /// Note: Only interrupts events that are enabled are processed //------------------------------------------------------------------------------ void usb_general_interrupt(void) { //TRACE_DEBUG("usb_general_interrupt\n\r"); // ---------- DEVICE events management ----------------------------------- // ----------------------------------------------------------------------- //- VBUS state detection // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled() && Is_usb_id_device()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_connected = TRUE; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); //jcb Usb_enable_reset_interrupt(); //usb_start_device(); USBD_Connect();//Usb_attach(); } else { TRACE_DEBUG("VBUS low\n\r"); USBD_Disconnect(); Usb_device_stop_hnp(); TRACE_DEBUG("Usb_select_device4\n\r"); Usb_select_device(); Clear_all_user_request(); Usb_vbus_off_action(); usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); } } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Device start of frame received if (Is_usb_sof() && Is_sof_interrupt_enabled()) { // TRACE_DEBUG_WP("F"); // device Usb_ack_sof(); Usb_sof_action(); //sof_seen_in_session = TRUE; otg_last_sof_received = UDFNUML; // store last frame number received } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Device Suspend event (no more USB activity detected) if (Is_usb_suspend()) { //&& Is_suspend_interrupt_enabled()) { //TRACE_DEBUG_WP("D\n\r"); // 1st : B-PERIPH mode ? if (Is_usb_id_device()) { // HNP Handler TRACE_DEBUG("HNP Handler\n\r"); //TRACE_DEBUG("device_state = %d\n\r", device_state); //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); if (Is_host_requested_hnp() // "b_hnp_enable" feature received && (Is_session_started_with_srp() || Is_user_requested_hnp() )) { if (otg_device_nb_hnp_retry == 0) { otg_features_supported &= ~USBFeatureRequest_OTG_B_HNP_ENABLE; } else { Ack_user_request_hnp(); Usb_ack_hnp_error_interrupt(); Usb_ack_role_exchange_interrupt(); Usb_enable_role_exchange_interrupt(); Usb_enable_hnp_error_interrupt(); Usb_device_initiate_hnp(); otg_device_nb_hnp_retry--; } } else { // Remote wake-up handler //TRACE_DEBUG("Remote wake-up handler\n\r"); //TRACE_DEBUG("device_state = %d\n\r", device_state); //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0)) { //TRACE_DEBUG("enabled\n\r"); // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume // So the SUSPE enable bit must be cleared to avoid redundant interrupt // **************** // Please note also that is Vbus is lost during an upstream resume (Host disconnection), // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent) // remains set after the event, so that a good way to handle this feature is : // Usb_initiate_remote_wake_up(); // while (Is_usb_pending_remote_wake_up()) // { // if (Is_usb_vbus_low()) // { // // Emergency action (reset macro, etc.) if Vbus lost during resuming // break; // } // } // Usb_ack_remote_wake_up_start(); // **************** } else { //TRACE_DEBUG("disabled: %d %d\n\r", usb_configuration_nb, remote_wakeup_feature); // No remote wake-up supported Usb_send_event(EVT_USB_SUSPEND); } } } else { //TRACE_DEBUG("ici\n\r"); // A-PERIPH mode (will cause a session end, handled in usb_host_task.c) Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); //jcb Usb_ack_suspend(); } } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Wake up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) { TRACE_DEBUG("W\n\r"); Usb_unfreeze_clock(); Usb_send_event(EVT_USB_WAKE_UP); } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - Resume state bus detection if (Is_usb_resume() && Is_resume_interrupt_enabled()) { TRACE_DEBUG("Resume state bus detect\n\r"); Usb_send_event(EVT_USB_RESUME); } // ----------------------------------------------------------------------- /// Device // ----------------------------------------------------------------------- // - USB bus reset detection if (Is_usb_reset()&& Is_reset_interrupt_enabled()) { TRACE_DEBUG_WP("B\n\r"); if (Is_usb_id_host()) { //TRACE_DEBUG_WP("id_host\n\r"); dev_configure_endpoint(EP_CONTROL, TYPE_CONTROL, DIRECTION_OUT, SIZE_64, ONE_BANK, NYET_DISABLED); } // First initialization is important to be synchronized // A reset must first have been received if (device_state == A_PERIPHERAL) { //TRACE_DEBUG_WP("r A_PERIPHERAL\n\r"); otg_last_sof_received = UDFNUML; otg_last_sof_stored = UDFNUML; Usb_ack_sof(); Usb_enable_sof_interrupt(); reset_received = TRUE; Timer16_set_counter(0); } Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } // ---------- OTG events management ------------------------------------ // --------------------------------------------------------------------- // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - OTG HNP Success detection if (Is_usb_role_exchange_interrupt() && Is_role_exchange_interrupt_enabled()) { // TRACE_DEBUG("OTG HNP detect\n\r"); Usb_ack_role_exchange_interrupt(); Host_ack_device_connection(); Host_ack_device_disconnection(); Otg_send_event(EVT_OTG_HNP_SUCCESS); End_session_with_srp(); Clear_otg_features_from_host(); if (Is_usb_id_host()) { // HOST (A- or B-) mode if ((device_state != A_PERIPHERAL) && (device_state != A_END_HNP_WAIT_VFALL)) { static volatile unsigned int jcb; // Current mode is A-HOST, device will take the A-PERIPHERAL role b_uut_device_state = B_PERIPHERAL; device_state = A_PERIPHERAL; usb_connected = FALSE; usb_configuration_nb = 0; Usb_select_device(); USBD_Connect();//Usb_attach(); Usb_unfreeze_clock(); Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Usb_device_stop_hnp(); Usb_ack_reset(); Timer16_set_counter(0); Usb_freeze_clock(); // USB clock can be freezed to slow down events and condition detection //jcb while (Timer16_get_counter_low() != 20); jcb=0; while( jcb <100000){ jcb++; } Usb_unfreeze_clock(); reset_received = FALSE; Usb_disable_sof_interrupt(); // will be set in the next OTG Timer IT (mandatory) Usb_enable_suspend_interrupt(); Usb_enable_reset_interrupt(); dev_configure_endpoint(EP_CONTROL, TYPE_CONTROL, DIRECTION_OUT, SIZE_64, ONE_BANK, NYET_DISABLED); } } else { // In B_HOST mode, the HNPREQ bit must not be cleared because it releases the bus in suspend mode (and sof can't start) if ((b_uut_device_state != B_HOST) && (b_uut_device_state != B_END_HNP_SUSPEND)) { static volatile unsigned int jcb2; // Current mode is B-PERIPHERAL, device will go into B-HOST role End_session_with_srp(); Clear_otg_features_from_host(); b_uut_device_state = B_HOST; device_state = DEVICE_ATTACHED; usb_connected = FALSE; usb_configuration_nb = 0; TRACE_DEBUG("Select host 3\n\r"); Usb_select_host(); TRACE_DEBUG("Send reset\n\r"); Host_send_reset(); // send the first RESET while (Host_is_reset()); TRACE_DEBUG("Reset passed\n\r"); jcb2=0; while( jcb2 <1000000){ jcb2++; } Host_enable_sof(); // start Host (sof) Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Clear_all_user_request(); TRACE_DEBUG("Select host 3\n\r"); } } } // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - OTG HNP Failure detection if (Is_usb_hnp() && Is_usb_hnp_error_interrupt()&& Is_hnp_error_interrupt_enabled()) { TRACE_DEBUG("OTG HNP failure\n\r"); Usb_device_stop_hnp(); Usb_disable_role_exchange_interrupt(); Usb_disable_hnp_error_interrupt(); Usb_ack_hnp_error_interrupt(); if (Is_usb_id_device()) { Otg_send_event(EVT_OTG_HNP_ERROR); Clear_all_user_request(); } } // ---------- HOST events management ----------------------------------- // --------------------------------------------------------------------- // ----------------------------------------------------------------------- /// Arbitrer // ----------------------------------------------------------------------- // - ID pin change detection if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) { TRACE_DEBUG("ID pin change\n\r"); TRACE_DEBUG("device_state = %d\n\r", device_state); TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state); Usb_device_stop_hnp(); Clear_all_user_request(); if(Is_usb_id_device()) { g_usb_mode = USB_MODE_DEVICE; } else { g_usb_mode = USB_MODE_HOST; } Usb_ack_id_transition(); if( g_usb_mode != g_old_usb_mode) { // Basic Debounce if(Is_usb_id_device()) { // Going into device mode Usb_send_event(EVT_USB_DEVICE_FUNCTION); b_uut_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; id_changed_to_host_event = DISABLE; } else { // Going into host mode b_uut_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; Usb_send_event(EVT_USB_HOST_FUNCTION); id_changed_to_host_event = ENABLE; } Usb_id_transition_action(); TRACE_INFO("Pin Id changed\n\r"); } } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - The device has been disconnected // JCB to be fix if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { TRACE_DEBUG("device disconnect\n\r"); host_disable_all_pipe(); Host_ack_device_disconnection(); device_state=DEVICE_DISCONNECTED; Usb_send_event(EVT_HOST_DISCONNECTION); TRACE_INFO("Device disconnected\n\r"); Host_device_disconnection_action(); Clear_all_user_request(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Device connection if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) { TRACE_DEBUG("device connect\n\r"); Host_ack_device_connection(); host_disable_all_pipe(); Host_device_connection_action(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Host Start of frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { //TRACE_DEBUG_WP("_"); // host Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; // delay timeout management for interrupt tranfer mode in host mode #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) if (private_sof_counter>=250) { // Count 1/4 sec private_sof_counter=0; for(i=0;i<MAX_EP_NB;i++) { if(it_pipe_str[i].enable==ENABLE) { save_pipe_nb=Host_get_selected_pipe(); Host_select_pipe(i); if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) { it_pipe_str[i].enable=DISABLE; it_pipe_str[i].status=PIPE_DELAY_TIMEOUT; Host_stop_pipe_interrupt(i); if (is_any_interrupt_pipe_active()==FALSE) { // If no more transfer is armed if (g_sav_int_sof_enable==FALSE) { Host_disable_sof_interrupt(); } } it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed); } Host_select_pipe(save_pipe_nb); } } } #endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE)) Host_sof_action(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // - Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { TRACE_DEBUG("Host wake up\n\r"); Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up ! Host_disable_remote_wakeup_interrupt(); // CAUTION HWUP can be cleared only when USB clock is active (not frozen)! Usb_unfreeze_clock(); // Enable clock on USB interface Host_enable_sof(); // start sending SOF Host_ack_hwup(); // Clear HWUP interrupt flag Host_ack_remote_wakeup(); Usb_send_event(EVT_HOST_HWUP); // Send software event Usb_send_event(EVT_HOST_REMOTE_WAKEUP); Host_hwup_action(); // Map custom action if (Is_usb_hnp()) { Usb_host_reject_hnp(); Usb_disable_hnp_error_interrupt(); Usb_disable_role_exchange_interrupt(); } Host_send_resume(); } // ----------------------------------------------------------------------- /// Host // ----------------------------------------------------------------------- // Remote Wake Up has been received if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) { TRACE_DEBUG("Remote wake up\n\r"); Host_disable_remote_wakeup_interrupt(); Host_disable_hwup_interrupt(); Host_ack_remote_wakeup(); Host_ack_hwup(); // Clear HWUP interrupt flag Usb_unfreeze_clock(); // Enable clock on USB interface Host_enable_sof(); // start sending SOF Usb_send_event(EVT_HOST_REMOTE_WAKEUP); Usb_send_event(EVT_HOST_HWUP); // Send software event if (Is_usb_hnp()) { Usb_host_reject_hnp(); Usb_disable_hnp_error_interrupt(); Usb_disable_role_exchange_interrupt(); } Host_send_resume(); } }
/** * Sends the requested USB descriptor to the host if available, or STALLs the * request. * \param pDriver Pointer to a USBDDriver instance. * \param type Type of the requested descriptor * \param index Index of the requested descriptor. * \param length Maximum number of bytes to return. */ static void GetDescriptor( const USBDDriver *pDriver, uint8_t type, uint8_t indexRDesc, uint32_t length) { const USBDeviceDescriptor *pDevice; const USBConfigurationDescriptor *pConfiguration; const USBDeviceQualifierDescriptor *pQualifier; const USBConfigurationDescriptor *pOtherSpeed; const USBGenericDescriptor **pStrings = (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; const USBGenericDescriptor *pString; uint8_t numStrings = pDriver->pDescriptors->numStrings; uint8_t terminateWithNull = 0; /* Use different set of descriptors depending on device speed */ /* By default, we uses full speed values */ pDevice = pDriver->pDescriptors->pFsDevice; pConfiguration = pDriver->pDescriptors->pFsConfiguration; /* HS, we try HS values */ if (USBD_HAL_IsHighSpeed()) { TRACE_DEBUG_WP("HS "); if (pDriver->pDescriptors->pHsDevice) pDevice = pDriver->pDescriptors->pHsDevice; if (pDriver->pDescriptors->pHsConfiguration) pConfiguration = pDriver->pDescriptors->pHsConfiguration; pQualifier = pDriver->pDescriptors->pHsQualifier; pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed; } else { TRACE_DEBUG_WP("FS "); pQualifier = pDriver->pDescriptors->pFsQualifier; pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed; } /* Check the descriptor type */ switch (type) { case USBGenericDescriptor_DEVICE: TRACE_INFO_WP("Dev "); /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice); } USBD_Write(0, pDevice, length, 0, 0); break; case USBGenericDescriptor_CONFIGURATION: TRACE_INFO_WP("Cfg "); /* Adjust length and send descriptor */ if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) { length = USBConfigurationDescriptor_GetTotalLength(pConfiguration); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pConfiguration, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); break; case USBGenericDescriptor_DEVICEQUALIFIER: TRACE_INFO_WP("Qua "); /* Check if descriptor exists */ if (!pQualifier) { USBD_Stall(0); } else { /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier); } USBD_Write(0, pQualifier, length, 0, 0); } break; case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: TRACE_INFO_WP("OSC "); /* Check if descriptor exists */ if (!pOtherSpeed) { USBD_Stall(0); } else { /* Adjust length and send descriptor */ if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) { length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pOtherSpeed, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; case USBGenericDescriptor_STRING: TRACE_INFO_WP("Str%d ", indexRDesc); /* Check if descriptor exists */ if (indexRDesc >= numStrings) { USBD_Stall(0); } else { pString = pStrings[indexRDesc]; /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength(pString)) { length = USBGenericDescriptor_GetLength(pString); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pString, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; default: TRACE_WARNING( "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r", type); USBD_Stall(0); } }