diff --git a/src/USBHost/IUSBEnumerator.h b/src/USBHost/IUSBEnumerator.h index d807c4b..4576d29 100644 --- a/src/USBHost/IUSBEnumerator.h +++ b/src/USBHost/IUSBEnumerator.h @@ -31,6 +31,7 @@ class IUSBEnumerator virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used virtual void parseConfigEntry(uint8_t type, uint8_t sub_type, uint8_t *data, uint32_t len) {}; + virtual void setEnumeratingDeviceIndex(int index) {}; }; #endif /*IUSBENUMERATOR_H_*/ diff --git a/src/USBHost/USBHost.cpp b/src/USBHost/USBHost.cpp index e0670fb..504da31 100644 --- a/src/USBHost/USBHost.cpp +++ b/src/USBHost/USBHost.cpp @@ -225,6 +225,8 @@ void USBHost::usb_process() if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) { deviceInUse[i] = true; + if(device_connected_callback) + device_connected_callback(i); } } while(0); @@ -960,6 +962,7 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato dev->setPid(data[10] | (data[11] << 8)); USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); + pEnumerator->setEnumeratingDeviceIndex(index); pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); res = getConfigurationDescriptor(dev, data, sizeof(data), &total_conf_descr_length); diff --git a/src/USBHost/USBHost.h b/src/USBHost/USBHost.h index 4a156fd..1536782 100644 --- a/src/USBHost/USBHost.h +++ b/src/USBHost/USBHost.h @@ -189,6 +189,15 @@ class USBHost : public USBHALHost { } } + + /** + * Callback for connected device index + */ + void setDeviceConnectedCallback(mbed::Callback callback) + { + device_connected_callback = callback; + } + /** * Instantiate to protect USB thread from accessing shared objects (USBConnectedDevices and Interfaces) */ @@ -287,6 +296,8 @@ class USBHost : public USBHALHost { // buffer for conf descriptor uint8_t data[415]; + mbed::Callback device_connected_callback = nullptr; + /** * Add a transfer on the TD linked list associated to an ED * diff --git a/src/USBHost/USBHostConf.h b/src/USBHost/USBHostConf.h index 7145219..17c830d 100644 --- a/src/USBHost/USBHostConf.h +++ b/src/USBHost/USBHostConf.h @@ -17,6 +17,8 @@ #ifndef USBHOST_CONF_H #define USBHOST_CONF_H +#define ARC_USB_FULL_SIZE (1) + #include "mbed_config.h" #include "Callback.h" #include "Arduino.h" diff --git a/src/USBHost/dbg.h b/src/USBHost/dbg.h index dd15be7..fbfce5d 100644 --- a/src/USBHost/dbg.h +++ b/src/USBHost/dbg.h @@ -18,7 +18,7 @@ #define USB_DEBUG_H //Debug is disabled by default -#define DEBUG 0 /*INFO,ERR,WARN*/ +#define DEBUG 4 /*INFO,ERR,WARN*/ #define DEBUG_TRANSFER 0 #define DEBUG_EP_STATE 0 #define DEBUG_EVENT 0 diff --git a/src/USBHostHub/USBHostHub.cpp b/src/USBHostHub/USBHostHub.cpp index 6854b6f..8b985cc 100644 --- a/src/USBHostHub/USBHostHub.cpp +++ b/src/USBHostHub/USBHostHub.cpp @@ -147,7 +147,7 @@ void USBHostHub::disconnect() if ((hub_intf == -1) && (intf_class == HUB_CLASS) && (intf_subclass == 0) && - (intf_protocol == 0)) { + ((intf_protocol == 0) || (intf_protocol == 1))) { hub_intf = intf_nb; return true; } diff --git a/src/targets/TARGET_STM/USBEndpoint_STM.cpp b/src/targets/TARGET_STM/USBEndpoint_STM.cpp index 3a6d880..47b00ee 100644 --- a/src/targets/TARGET_STM/USBEndpoint_STM.cpp +++ b/src/targets/TARGET_STM/USBEndpoint_STM.cpp @@ -178,7 +178,12 @@ USB_TYPE USBEndpoint::queueTransfer() } ep_queue.get(0); MBED_ASSERT(*addr == 0); +#if ARC_USB_FULL_SIZE + transfer_len = td_current->size; +#else transfer_len = td_current->size <= max_size ? td_current->size : max_size; +#endif + buf_start = (uint8_t *)td_current->currBufPtr; //Now add this free TD at this end of the queue diff --git a/src/targets/TARGET_STM/USBHALHost_STM.cpp b/src/targets/TARGET_STM/USBHALHost_STM.cpp index 1439c4d..cdcc7a8 100644 --- a/src/targets/TARGET_STM/USBHALHost_STM.cpp +++ b/src/targets/TARGET_STM/USBHALHost_STM.cpp @@ -91,6 +91,98 @@ uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chnum) // - URB_NOTREADY = a NAK, NYET, or not more than a couple of repeats of some of the errors that will // become URB_ERROR if they repeat several times in a row // +#if ARC_USB_FULL_SIZE +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState) +{ + USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData); + + HCTD *pTransferDescriptor = (HCTD *)pPriv->addr[uChannel]; + + + + if (pTransferDescriptor) + { + constexpr uint32_t uRetryCount = 10; + + uint32_t endpointType = pHcd->hc[uChannel].ep_type; + + if ((endpointType == EP_TYPE_INTR)) + { + // Disable the channel interrupt and retransfer below + pTransferDescriptor->state = USB_TYPE_IDLE ; + HAL_HCD_DisableInt(pHcd, uChannel); + } + else if ((endpointType == EP_TYPE_BULK) || (endpointType == EP_TYPE_CTRL)) + { + switch(urbState) + { + case URB_NOTREADY: + { + // If we have transferred any data then disable retries + if(pHcd->hc[uChannel].xfer_count > 0) + pTransferDescriptor->retry = 0xffffffff; // Disable retries + else + { + // if the retry count is 0 then initialize downward counting retry + // otherwise decrement retry count + if(pTransferDescriptor->retry == 0) + pTransferDescriptor->retry = uRetryCount; + else + pTransferDescriptor->retry--; + } + + // If our retry count has got down to 0 or we are an Ack then submit request again + if((pTransferDescriptor->retry == 0) || (pTransferDescriptor->size==0)) + { + // initialize downward counting retry + pTransferDescriptor->retry = uRetryCount; + + // resubmit the request. + HAL_HCD_HC_SubmitRequest(pHcd, uChannel, pHcd->hc[uChannel].ep_is_in, endpointType, !pTransferDescriptor->setup, (uint8_t *) pTransferDescriptor->currBufPtr, pTransferDescriptor->size, 0); + HAL_HCD_EnableInt(pHcd, uChannel); + } + } + break; + + case URB_DONE: + { + // this will be handled below for USB_TYPE_IDLE + pTransferDescriptor->state = USB_TYPE_IDLE; + } + break; + + case URB_ERROR: + { + // While USB_TYPE_ERROR in the endpoint state is used to activate error recovery, this value is actually never used. + // Going here will lead to a timeout at a higher layer, because of ep_queue.get() timeout, which will activate error + // recovery indirectly. + pTransferDescriptor->state = USB_TYPE_ERROR; + } + break; + + default: + { + pTransferDescriptor->state = USB_TYPE_PROCESSING; + } + break; + } + } + + if (pTransferDescriptor->state == USB_TYPE_IDLE) + { + // Disable retrues + pTransferDescriptor->retry = 0; + + // Update transfer descriptor buffer pointer + pTransferDescriptor->currBufPtr += HAL_HCD_HC_GetXferCount(pHcd, uChannel); + + // Call transferCompleted on correct object + void (USBHALHost::*func)(volatile uint32_t addr) = pPriv->transferCompleted; + (pPriv->inst->*func)(reinterpret_cast(pTransferDescriptor)); + } + } +} +#else void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) { USBHALHost_Private_t *priv = (USBHALHost_Private_t *)(hhcd->pData); @@ -168,6 +260,7 @@ void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, } } } +#endif USBHALHost *USBHALHost::instHost; @@ -346,8 +439,53 @@ void USBHALHost::_usbisr(void) } } + void USBHALHost::UsbIrqhandler() { - HAL_HCD_IRQHandler((HCD_HandleTypeDef *)usb_hcca); -} +#if ARC_USB_FULL_SIZE + // fix from Lix Paulian : https://community.st.com/t5/stm32-mcus-products/stm32f4-stm32f7-usb-host-core-interrupt-flood/td-p/436225/page/4 + // Change to also stop flooding of channel halt interrupt + uint32_t ch_num; + HCD_HandleTypeDef* hhcd = (HCD_HandleTypeDef *)usb_hcca; + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF) && hhcd->Init.dma_enable == 0) + { + for (ch_num = 0; ch_num < hhcd->Init.Host_channels; ch_num++) + { + // workaround the interrupts flood issue: re-enable NAK interrupt + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINT_NAK; + + // workaround the interrupts flood issue: re-enable CHH interrupt + if(hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINT_CHH; + } + } + + + HAL_HCD_IRQHandler((HCD_HandleTypeDef *)usb_hcca); + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT) && hhcd->Init.dma_enable == 0) + { + for (ch_num = 0; ch_num < hhcd->Init.Host_channels; ch_num++) + { + if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) || (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK)) + { + if (USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) + { + // workaround the interrupts flood issue: disable NAK interrupt + USBx_HC(ch_num)->HCINTMSK &= ~USB_OTG_HCINT_NAK; + } + + if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) && (hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL)) + { + // workaround the interrupts flood issue: disable CHH interrupt + USBx_HC(ch_num)->HCINTMSK &= ~USB_OTG_HCINT_CHH; + } + } + } + } +#else + HAL_HCD_IRQHandler((HCD_HandleTypeDef *)usb_hcca); #endif +} +#endif \ No newline at end of file