From c900c951a339758d8ec34368b226a900e3f22ac0 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Tue, 4 Jul 2017 19:09:39 -0300 Subject: USBH: MSD: Rework to prevent race conditions on unload --- os/hal/include/usbh/dev/msd.h | 12 +--- os/hal/src/usbh/hal_usbh_msd.c | 127 ++++++++++++++--------------------------- 2 files changed, 46 insertions(+), 93 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/dev/msd.h b/os/hal/include/usbh/dev/msd.h index 84179c5..4eef6d6 100644 --- a/os/hal/include/usbh/dev/msd.h +++ b/os/hal/include/usbh/dev/msd.h @@ -58,6 +58,9 @@ struct USBHMassStorageLUNDriver { const struct USBHMassStorageDriverVMT *vmt; _base_block_device_data + /* for serializing access to the LUN driver */ + mutex_t mtx; + BlockDeviceInfo info; USBHMassStorageDriver *msdp; @@ -68,11 +71,6 @@ struct USBHMassStorageDriver { /* inherited from abstract class driver */ _usbh_base_classdriver_data - /* for LUN request serialization, can be removed - * if the driver is configured to support only one LUN - * per USBHMassStorageDriver instance */ - mutex_t mtx; - usbh_ep_t epin; usbh_ep_t epout; uint8_t ifnum; @@ -98,11 +96,7 @@ extern USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES]; #ifdef __cplusplus extern "C" { #endif - /* Mass Storage Driver */ - void usbhmsdObjectInit(USBHMassStorageDriver *msdp); - /* Mass Storage LUN Driver (block driver) */ - void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp); void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp); void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp); diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index b564e8e..061c754 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -62,9 +62,7 @@ #define uerr(f, ...) do {} while(0) #endif - - - +static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp); /*===========================================================================*/ /* USB Class driver loader for MSD */ @@ -187,15 +185,7 @@ alloc_ok: MSBLKD[i].next = msdp->luns; msdp->luns = &MSBLKD[i]; MSBLKD[i].msdp = msdp; - - osalSysLock(); MSBLKD[i].state = BLK_ACTIVE; /* transition directly to active, instead of BLK_STOP */ - osalSysUnlock(); - - /* connect the LUN (TODO: review if it's best to leave the LUN disconnected) */ - msdp->dev = dev; - usbhmsdLUNConnect(&MSBLKD[i]); - msdp->dev = NULL; luns--; } } @@ -212,25 +202,15 @@ static void _msd_unload(usbh_baseclassdriver_t *drv) { USBHMassStorageDriver *const msdp = (USBHMassStorageDriver *)drv; USBHMassStorageLUNDriver *lunp = msdp->luns; - osalMutexLock(&msdp->mtx); - osalSysLock(); - usbhEPCloseS(&msdp->epin); - usbhEPCloseS(&msdp->epout); + /* disconnect all LUNs */ while (lunp) { - lunp->state = BLK_STOP; + usbhmsdLUNDisconnect(lunp); + usbhmsdLUNObjectDeinit(lunp); lunp = lunp->next; } - osalSysUnlock(); - osalMutexUnlock(&msdp->mtx); - /* now that the LUNs are idle, deinit them */ - lunp = msdp->luns; - osalSysLock(); - while (lunp) { - usbhmsdLUNObjectInit(lunp); - lunp = lunp->next; - } - osalSysUnlock(); + usbhEPClose(&msdp->epin); + usbhEPClose(&msdp->epout); } @@ -238,8 +218,6 @@ static void _msd_unload(usbh_baseclassdriver_t *drv) { /* MSD Class driver operations (Bulk-Only transport) */ /*===========================================================================*/ - - /* USB Bulk Only Transport SCSI Command block wrapper */ typedef PACKED_STRUCT { uint32_t dCBWSignature; @@ -704,11 +682,23 @@ static const struct USBHMassStorageDriverVMT blk_vmt = { (bool (*)(void *, BlockDeviceInfo *))usbhmsdLUNGetInfo }; -void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp) { +static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp) { + osalDbgCheck(lunp != NULL); + osalMutexLock(&lunp->mtx); + lunp->msdp = NULL; + lunp->next = NULL; + memset(&lunp->info, 0, sizeof(lunp->info)); + lunp->state = BLK_STOP; + osalMutexUnlock(&lunp->mtx); +} + +static void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); memset(lunp, 0, sizeof(*lunp)); lunp->vmt = &blk_vmt; lunp->state = BLK_STOP; + osalMutexObjectInit(&lunp->mtx); + /* Unnecessary because of the memset: lunp->msdp = NULL; lunp->next = NULL; @@ -737,24 +727,19 @@ void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp) { } bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { - USBHMassStorageDriver *const msdp = lunp->msdp; + osalDbgCheck(lunp != NULL); + osalDbgCheck(lunp->msdp != NULL); msd_result_t res; - osalDbgCheck(msdp != NULL); - osalSysLock(); - //osalDbgAssert((lunp->state == BLK_ACTIVE) || (lunp->state == BLK_READY), - // "invalid state"); + osalMutexLock(&lunp->mtx); if (lunp->state == BLK_READY) { - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return HAL_SUCCESS; } else if (lunp->state != BLK_ACTIVE) { - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return HAL_FAILED; } lunp->state = BLK_CONNECTING; - osalSysUnlock(); - - osalMutexLock(&msdp->mtx); { USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq); @@ -821,40 +806,36 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { uinfo("MSD Connected."); - osalMutexUnlock(&msdp->mtx); - osalSysLock(); lunp->state = BLK_READY; - osalSysUnlock(); - + osalMutexUnlock(&lunp->mtx); return HAL_SUCCESS; /* Connection failed, state reset to BLK_ACTIVE.*/ failed: - osalMutexUnlock(&msdp->mtx); - osalSysLock(); lunp->state = BLK_ACTIVE; - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return HAL_FAILED; } bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); - osalSysLock(); + + osalMutexLock(&lunp->mtx); osalDbgAssert((lunp->state == BLK_ACTIVE) || (lunp->state == BLK_READY), "invalid state"); + if (lunp->state == BLK_ACTIVE) { - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return HAL_SUCCESS; } lunp->state = BLK_DISCONNECTING; - osalSysUnlock(); //TODO: complete - osalSysLock(); lunp->state = BLK_ACTIVE; - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); + return HAL_SUCCESS; } @@ -867,15 +848,13 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, msd_result_t res; uint32_t actual_len; - osalSysLock(); + osalMutexLock(&lunp->mtx); if (lunp->state != BLK_READY) { - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return ret; } lunp->state = BLK_READING; - osalSysUnlock(); - osalMutexLock(&lunp->msdp->mtx); while (n) { if (n > 0xffff) { blocks = 0xffff; @@ -900,15 +879,8 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, ret = HAL_SUCCESS; exit: - osalMutexUnlock(&lunp->msdp->mtx); - osalSysLock(); - if (lunp->state == BLK_READING) { - lunp->state = BLK_READY; - } else { - osalDbgCheck(lunp->state == BLK_STOP); - uwarn("MSD: State = BLK_STOP"); - } - osalSysUnlock(); + lunp->state = BLK_READY; + osalMutexUnlock(&lunp->mtx); return ret; } @@ -921,15 +893,13 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk, msd_result_t res; uint32_t actual_len; - osalSysLock(); + osalMutexLock(&lunp->mtx); if (lunp->state != BLK_READY) { - osalSysUnlock(); + osalMutexUnlock(&lunp->mtx); return ret; } lunp->state = BLK_WRITING; - osalSysUnlock(); - osalMutexLock(&lunp->msdp->mtx); while (n) { if (n > 0xffff) { blocks = 0xffff; @@ -954,15 +924,8 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk, ret = HAL_SUCCESS; exit: - osalMutexUnlock(&lunp->msdp->mtx); - osalSysLock(); - if (lunp->state == BLK_WRITING) { - lunp->state = BLK_READY; - } else { - osalDbgCheck(lunp->state == BLK_STOP); - uwarn("MSD: State = BLK_STOP"); - } - osalSysUnlock(); + lunp->state = BLK_READY; + osalMutexUnlock(&lunp->mtx); return ret; } @@ -982,23 +945,19 @@ bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip) { bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); - blkstate_t state; - osalSysLock(); - state = lunp->state; - osalSysUnlock(); - return (state >= BLK_ACTIVE); + return (lunp->state >= BLK_ACTIVE); } bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); + //TODO: Implement return FALSE; } -void usbhmsdObjectInit(USBHMassStorageDriver *msdp) { +static void usbhmsdObjectInit(USBHMassStorageDriver *msdp) { osalDbgCheck(msdp != NULL); memset(msdp, 0, sizeof(*msdp)); msdp->info = &usbhmsdClassDriverInfo; - osalMutexObjectInit(&msdp->mtx); } void usbhmsdInit(void) { -- cgit v1.2.3 From c9388668449f9d686b1e4df14f9143263cc0fafc Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 18:29:44 -0300 Subject: USBH: moved definition of driver to LLD --- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 7 +++++++ os/hal/src/hal_usbh.c | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'os/hal') diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index 5954cb2..a949847 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -105,6 +105,13 @@ static void _try_commit_np(USBHDriver *host); static void otg_rxfifo_flush(USBHDriver *usbp); static void otg_txfifo_flush(USBHDriver *usbp, uint32_t fifo); +#if STM32_USBH_USE_OTG1 +USBHDriver USBHD1; +#endif +#if STM32_USBH_USE_OTG2 +USBHDriver USBHD2; +#endif + /*===========================================================================*/ /* Little helper functions. */ /*===========================================================================*/ diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index d242086..9e6c8eb 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -62,14 +62,6 @@ #define uerr(f, ...) do {} while(0) #endif -#if STM32_USBH_USE_OTG1 -USBHDriver USBHD1; -#endif -#if STM32_USBH_USE_OTG2 -USBHDriver USBHD2; -#endif - - static void _classdriver_process_device(usbh_device_t *dev); static bool _classdriver_load(usbh_device_t *dev, uint8_t class, uint8_t subclass, uint8_t protocol, uint8_t *descbuff, uint16_t rem); -- cgit v1.2.3 From 025ca5345a8ffbb7de3b1c64fb0a5ddbbdacd3b0 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 18:30:46 -0300 Subject: USBH: Added mechanism for out-of-tree class driver enumeration --- os/hal/include/hal_usbh.h | 6 ++++++ os/hal/include/usbh/dev/aoa.h | 4 ---- os/hal/include/usbh/dev/ftdi.h | 7 ------- os/hal/include/usbh/dev/hid.h | 6 ------ os/hal/include/usbh/dev/hub.h | 4 ---- os/hal/include/usbh/dev/msd.h | 3 --- os/hal/include/usbh/dev/uvc.h | 8 -------- os/hal/src/hal_usbh.c | 42 +++++++++++++++++++---------------------- os/hal/src/usbh/hal_usbh_aoa.c | 8 +++++--- os/hal/src/usbh/hal_usbh_ftdi.c | 15 +++++++++------ os/hal/src/usbh/hal_usbh_hid.c | 8 +++++--- os/hal/src/usbh/hal_usbh_hub.c | 21 ++++++++++++--------- os/hal/src/usbh/hal_usbh_msd.c | 18 ++++++++++-------- os/hal/src/usbh/hal_usbh_uvc.c | 38 ++++++++++++++++++------------------- 14 files changed, 85 insertions(+), 103 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index b8c229a..f6e78e9 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -48,6 +48,10 @@ #define HAL_USBH_USE_HID FALSE #endif +#ifndef HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS +#define HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS FALSE +#endif + #define HAL_USBH_USE_IAD HAL_USBH_USE_UVC #if (HAL_USE_USBH == TRUE) || defined(__DOXYGEN__) @@ -402,8 +406,10 @@ extern "C" { typedef struct usbh_classdriver_vmt usbh_classdriver_vmt_t; struct usbh_classdriver_vmt { + void (*init)(void); usbh_baseclassdriver_t *(*load)(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); void (*unload)(usbh_baseclassdriver_t *drv); + /* TODO: add power control, suspend, etc */ }; struct usbh_classdriverinfo { diff --git a/os/hal/include/usbh/dev/aoa.h b/os/hal/include/usbh/dev/aoa.h index 636768a..a7f1c1b 100644 --- a/os/hal/include/usbh/dev/aoa.h +++ b/os/hal/include/usbh/dev/aoa.h @@ -140,12 +140,8 @@ extern USBHAOADriver USBHAOAD[HAL_USBHAOA_MAX_INSTANCES]; extern "C" { #endif /* AOA device driver */ - void usbhaoaObjectInit(USBHAOADriver *aoap); void usbhaoaChannelStart(USBHAOADriver *aoap); void usbhaoaChannelStop(USBHAOADriver *aoap); - - /* global initializer */ - void usbhaoaInit(void); #ifdef __cplusplus } #endif diff --git a/os/hal/include/usbh/dev/ftdi.h b/os/hal/include/usbh/dev/ftdi.h index bfa3103..eedb056 100644 --- a/os/hal/include/usbh/dev/ftdi.h +++ b/os/hal/include/usbh/dev/ftdi.h @@ -138,16 +138,9 @@ extern USBHFTDIPortDriver FTDIPD[HAL_USBHFTDI_MAX_PORTS]; #ifdef __cplusplus extern "C" { #endif - /* FTDI device driver */ - void usbhftdiObjectInit(USBHFTDIDriver *ftdip); - /* FTDI port driver */ - void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp); void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config); void usbhftdipStop(USBHFTDIPortDriver *ftdipp); - - /* global initializer */ - void usbhftdiInit(void); #ifdef __cplusplus } #endif diff --git a/os/hal/include/usbh/dev/hid.h b/os/hal/include/usbh/dev/hid.h index 0d6b894..1dbc486 100644 --- a/os/hal/include/usbh/dev/hid.h +++ b/os/hal/include/usbh/dev/hid.h @@ -112,9 +112,6 @@ extern USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES]; #ifdef __cplusplus extern "C" { #endif - /* HID Driver */ - void usbhHIDObjectInit(USBHHIDDriver *hidp); - /* HID Common API */ usbh_urbstatus_t usbhhidGetReport(USBHHIDDriver *hidp, uint8_t report_id, usbhhid_reporttype_t report_type, @@ -136,9 +133,6 @@ extern "C" { } void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg); - - /* global initializer */ - void usbhhidInit(void); #ifdef __cplusplus } #endif diff --git a/os/hal/include/usbh/dev/hub.h b/os/hal/include/usbh/dev/hub.h index 924ebec..406fbaf 100644 --- a/os/hal/include/usbh/dev/hub.h +++ b/os/hal/include/usbh/dev/hub.h @@ -88,10 +88,6 @@ static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t 0); } -void usbhhubObjectInit(USBHHubDriver *hubdp); - -void usbhhubInit(void); - #else static inline usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host, diff --git a/os/hal/include/usbh/dev/msd.h b/os/hal/include/usbh/dev/msd.h index 4eef6d6..f73836f 100644 --- a/os/hal/include/usbh/dev/msd.h +++ b/os/hal/include/usbh/dev/msd.h @@ -109,9 +109,6 @@ extern "C" { bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip); bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp); - - /* global initializer */ - void usbhmsdInit(void); #ifdef __cplusplus } #endif diff --git a/os/hal/include/usbh/dev/uvc.h b/os/hal/include/usbh/dev/uvc.h index c68a082..bc46a71 100644 --- a/os/hal/include/usbh/dev/uvc.h +++ b/os/hal/include/usbh/dev/uvc.h @@ -394,9 +394,6 @@ extern USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES]; #ifdef __cplusplus extern "C" { #endif - - void usbhuvcObjectInit(USBHUVCDriver *uvcd); - static inline usbhuvc_state_t usbhuvcGetState(USBHUVCDriver *uvcd) { return uvcd->state; } @@ -457,11 +454,6 @@ extern "C" { static inline void usbhuvcFreeStatusMessage(USBHUVCDriver *uvcdp, usbhuvc_message_status_t *msg) { chPoolFree(&uvcdp->mp_status, msg); } - - - /* global initializer */ - void usbhuvcInit(void); - #ifdef __cplusplus } #endif diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index 9e6c8eb..d0d3cb7 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -66,6 +66,12 @@ static void _classdriver_process_device(usbh_device_t *dev); static bool _classdriver_load(usbh_device_t *dev, uint8_t class, uint8_t subclass, uint8_t protocol, uint8_t *descbuff, uint16_t rem); +#if HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS +#include "usbh_additional_class_drivers.h" +#ifndef HAL_USBH_ADDITIONAL_CLASS_DRIVERS +#error "Must define HAL_USBH_ADDITIONAL_CLASS_DRIVERS" +#endif +#endif /*===========================================================================*/ /* Checks. */ @@ -105,28 +111,6 @@ void usbhObjectInit(USBHDriver *usbh) { #endif } -void usbhInit(void) { -#if HAL_USBH_USE_FTDI - usbhftdiInit(); -#endif -#if HAL_USBH_USE_AOA - usbhaoaInit(); -#endif -#if HAL_USBH_USE_MSD - usbhmsdInit(); -#endif -#if HAL_USBH_USE_HID - usbhhidInit(); -#endif -#if HAL_USBH_USE_UVC - usbhuvcInit(); -#endif -#if HAL_USBH_USE_HUB - usbhhubInit(); -#endif - usbh_lld_init(); -} - void usbhStart(USBHDriver *usbh) { usbDbgInit(usbh); @@ -1236,6 +1220,7 @@ void usbhMainLoop(USBHDriver *usbh) { static usbh_baseclassdriver_t *iad_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void iad_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t usbhiadClassDriverVMT = { + NULL, iad_load, iad_unload }; @@ -1290,8 +1275,11 @@ static void iad_unload(usbh_baseclassdriver_t *drv) { /*===========================================================================*/ /* Class driver loader. */ /*===========================================================================*/ - static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = { +#if HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS + /* user-defined out of tree class drivers */ + HAL_USBH_ADDITIONAL_CLASS_DRIVERS +#endif #if HAL_USBH_USE_FTDI &usbhftdiClassDriverInfo, #endif @@ -1431,6 +1419,14 @@ exit: } } +void usbhInit(void) { + uint8_t i; + for (i = 0; i < sizeof_array(usbh_classdrivers_lookup); i++) { + if (usbh_classdrivers_lookup[i]->vmt->init) { + usbh_classdrivers_lookup[i]->vmt->init(); + } + } +} #endif diff --git a/os/hal/src/usbh/hal_usbh_aoa.c b/os/hal/src/usbh/hal_usbh_aoa.c index 1fa49f8..db348c0 100644 --- a/os/hal/src/usbh/hal_usbh_aoa.c +++ b/os/hal/src/usbh/hal_usbh_aoa.c @@ -124,8 +124,10 @@ USBHAOADriver USBHAOAD[HAL_USBHAOA_MAX_INSTANCES]; static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _aoa_unload(usbh_baseclassdriver_t *drv); +static void _aoa_init(void); static const usbh_classdriver_vmt_t class_driver_vmt = { + _aoa_init, _aoa_load, _aoa_unload }; @@ -658,7 +660,7 @@ static bool _send_string(usbh_device_t *dev, uint8_t index, const char *string) return HAL_SUCCESS; } -void usbhaoaObjectInit(USBHAOADriver *aoap) { +static void _object_init(USBHAOADriver *aoap) { osalDbgCheck(aoap != NULL); memset(aoap, 0, sizeof(*aoap)); aoap->info = &usbhaoaClassDriverInfo; @@ -668,10 +670,10 @@ void usbhaoaObjectInit(USBHAOADriver *aoap) { aoap->channel.state = USBHAOA_CHANNEL_STATE_STOP; } -void usbhaoaInit(void) { +static void _aoa_init(void) { uint8_t i; for (i = 0; i < HAL_USBHAOA_MAX_INSTANCES; i++) { - usbhaoaObjectInit(&USBHAOAD[i]); + _object_init(&USBHAOAD[i]); } } diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index ce96958..9822969 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -62,16 +62,19 @@ #define uerr(f, ...) do {} while(0) #endif +static void _ftdip_object_init(USBHFTDIPortDriver *ftdipp); /*===========================================================================*/ /* USB Class driver loader for FTDI */ /*===========================================================================*/ USBHFTDIDriver USBHFTDID[HAL_USBHFTDI_MAX_INSTANCES]; +static void _ftdi_init(void); static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _ftdi_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t class_driver_vmt = { + _ftdi_init, _ftdi_load, _ftdi_unload }; @@ -229,7 +232,7 @@ static void _ftdi_unload(usbh_baseclassdriver_t *drv) { osalSysLock(); while (ftdipp) { USBHFTDIPortDriver *next = ftdipp->next; - usbhftdipObjectInit(ftdipp); + _ftdip_object_init(ftdipp); ftdipp = next; } osalSysUnlock(); @@ -700,27 +703,27 @@ void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config osalMutexUnlock(&ftdipp->ftdip->mtx); } -void usbhftdiObjectInit(USBHFTDIDriver *ftdip) { +static void _ftdi_object_init(USBHFTDIDriver *ftdip) { osalDbgCheck(ftdip != NULL); memset(ftdip, 0, sizeof(*ftdip)); ftdip->info = &usbhftdiClassDriverInfo; osalMutexObjectInit(&ftdip->mtx); } -void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp) { +static void _ftdip_object_init(USBHFTDIPortDriver *ftdipp) { osalDbgCheck(ftdipp != NULL); memset(ftdipp, 0, sizeof(*ftdipp)); ftdipp->vmt = &async_channel_vmt; ftdipp->state = USBHFTDIP_STATE_STOP; } -void usbhftdiInit(void) { +static void _ftdi_init(void) { uint8_t i; for (i = 0; i < HAL_USBHFTDI_MAX_INSTANCES; i++) { - usbhftdiObjectInit(&USBHFTDID[i]); + _ftdi_object_init(&USBHFTDID[i]); } for (i = 0; i < HAL_USBHFTDI_MAX_PORTS; i++) { - usbhftdipObjectInit(&FTDIPD[i]); + _ftdip_object_init(&FTDIPD[i]); } } diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index e98dff7..4b20fd3 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -74,10 +74,12 @@ USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES]; +static void _hid_init(void); static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _hid_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t class_driver_vmt = { + _hid_init, _hid_load, _hid_unload }; @@ -305,17 +307,17 @@ usbh_urbstatus_t usbhhidSetProtocol(USBHHIDDriver *hidp, uint8_t protocol) { protocol, hidp->ifnum, 0, NULL); } -void usbhhidObjectInit(USBHHIDDriver *hidp) { +static void _hid_object_init(USBHHIDDriver *hidp) { osalDbgCheck(hidp != NULL); memset(hidp, 0, sizeof(*hidp)); hidp->info = &usbhhidClassDriverInfo; hidp->state = USBHHID_STATE_STOP; } -void usbhhidInit(void) { +static void _hid_init(void) { uint8_t i; for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) { - usbhhidObjectInit(&USBHHIDD[i]); + _hid_object_init(&USBHHIDD[i]); } } diff --git a/os/hal/src/usbh/hal_usbh_hub.c b/os/hal/src/usbh/hal_usbh_hub.c index 3a84175..c9bbe9b 100644 --- a/os/hal/src/usbh/hal_usbh_hub.c +++ b/os/hal/src/usbh/hal_usbh_hub.c @@ -63,12 +63,15 @@ USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES]; static usbh_port_t USBHPorts[HAL_USBHHUB_MAX_PORTS]; -static usbh_baseclassdriver_t *hub_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); -static void hub_unload(usbh_baseclassdriver_t *drv); +static void _hub_init(void); +static usbh_baseclassdriver_t *_hub_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); +static void _hub_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t usbhhubClassDriverVMT = { - hub_load, - hub_unload + _hub_init, + _hub_load, + _hub_unload }; + const usbh_classdriverinfo_t usbhhubClassDriverInfo = { 0x09, 0x00, -1, "HUB", &usbhhubClassDriverVMT }; @@ -137,7 +140,7 @@ static void _urb_complete(usbh_urb_t *urb) { usbhURBSubmitI(urb); } -static usbh_baseclassdriver_t *hub_load(usbh_device_t *dev, +static usbh_baseclassdriver_t *_hub_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; @@ -261,7 +264,7 @@ alloc_ok: return (usbh_baseclassdriver_t *)hubdp; } -static void hub_unload(usbh_baseclassdriver_t *drv) { +static void _hub_unload(usbh_baseclassdriver_t *drv) { osalDbgCheck(drv != NULL); USBHHubDriver *const hubdp = (USBHHubDriver *)drv; @@ -283,16 +286,16 @@ static void hub_unload(usbh_baseclassdriver_t *drv) { } -void usbhhubObjectInit(USBHHubDriver *hubdp) { +static void _object_init(USBHHubDriver *hubdp) { osalDbgCheck(hubdp != NULL); memset(hubdp, 0, sizeof(*hubdp)); hubdp->info = &usbhhubClassDriverInfo; } -void usbhhubInit(void) { +static void _hub_init(void) { uint8_t i; for (i = 0; i < HAL_USBHHUB_MAX_INSTANCES; i++) { - usbhhubObjectInit(&USBHHUBD[i]); + _object_init(&USBHHUBD[i]); } } diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index 061c754..f2a4e39 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -62,7 +62,7 @@ #define uerr(f, ...) do {} while(0) #endif -static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp); +static void _lun_object_deinit(USBHMassStorageLUNDriver *lunp); /*===========================================================================*/ /* USB Class driver loader for MSD */ @@ -70,10 +70,12 @@ static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp); USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES]; +static void _msd_init(void); static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _msd_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t class_driver_vmt = { + _msd_init, _msd_load, _msd_unload }; @@ -205,7 +207,7 @@ static void _msd_unload(usbh_baseclassdriver_t *drv) { /* disconnect all LUNs */ while (lunp) { usbhmsdLUNDisconnect(lunp); - usbhmsdLUNObjectDeinit(lunp); + _lun_object_deinit(lunp); lunp = lunp->next; } @@ -682,7 +684,7 @@ static const struct USBHMassStorageDriverVMT blk_vmt = { (bool (*)(void *, BlockDeviceInfo *))usbhmsdLUNGetInfo }; -static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp) { +static void _lun_object_deinit(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); osalMutexLock(&lunp->mtx); lunp->msdp = NULL; @@ -692,7 +694,7 @@ static void usbhmsdLUNObjectDeinit(USBHMassStorageLUNDriver *lunp) { osalMutexUnlock(&lunp->mtx); } -static void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp) { +static void _lun_object_init(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); memset(lunp, 0, sizeof(*lunp)); lunp->vmt = &blk_vmt; @@ -954,19 +956,19 @@ bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp) { return FALSE; } -static void usbhmsdObjectInit(USBHMassStorageDriver *msdp) { +static void _msd_object_init(USBHMassStorageDriver *msdp) { osalDbgCheck(msdp != NULL); memset(msdp, 0, sizeof(*msdp)); msdp->info = &usbhmsdClassDriverInfo; } -void usbhmsdInit(void) { +static void _msd_init(void) { uint8_t i; for (i = 0; i < HAL_USBHMSD_MAX_INSTANCES; i++) { - usbhmsdObjectInit(&USBHMSD[i]); + _msd_object_init(&USBHMSD[i]); } for (i = 0; i < HAL_USBHMSD_MAX_LUNS; i++) { - usbhmsdLUNObjectInit(&MSBLKD[i]); + _lun_object_init(&MSBLKD[i]); } } #endif diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index b0507a0..ac3663e 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -66,14 +66,15 @@ USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES]; - -static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev, +static void _uvc_init(void); +static usbh_baseclassdriver_t *_uvc_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); -static void uvc_unload(usbh_baseclassdriver_t *drv); +static void _uvc_unload(usbh_baseclassdriver_t *drv); static const usbh_classdriver_vmt_t class_driver_vmt = { - uvc_load, - uvc_unload + _uvc_init, + _uvc_load, + _uvc_unload }; const usbh_classdriverinfo_t usbhuvcClassDriverInfo = { 0x0e, 0x03, 0x00, "UVC", &class_driver_vmt @@ -512,17 +513,7 @@ uint32_t usbhuvcEstimateRequiredEPSize(USBHUVCDriver *uvcdp, const uint8_t *form return (sz * mul) / div + 12; } -void usbhuvcObjectInit(USBHUVCDriver *uvcdp) { - osalDbgCheck(uvcdp != NULL); - memset(uvcdp, 0, sizeof(*uvcdp)); - uvcdp->info = &usbhuvcClassDriverInfo; - chMBObjectInit(&uvcdp->mb, uvcdp->mb_buff, HAL_USBHUVC_MAX_MAILBOX_SZ); - chMtxObjectInit(&uvcdp->mtx); - uvcdp->state = USBHUVC_STATE_STOP; -} - - -static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { +static usbh_baseclassdriver_t *_uvc_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { USBHUVCDriver *uvcdp; uint8_t i; @@ -710,7 +701,7 @@ alloc_ok: return (usbh_baseclassdriver_t *)uvcdp; } -static void uvc_unload(usbh_baseclassdriver_t *drv) { +static void _uvc_unload(usbh_baseclassdriver_t *drv) { USBHUVCDriver *const uvcdp = (USBHUVCDriver *)drv; usbhuvcStreamStop(uvcdp); @@ -727,10 +718,19 @@ static void uvc_unload(usbh_baseclassdriver_t *drv) { osalSysUnlock(); } -void usbhuvcInit(void) { +static void _object_init(USBHUVCDriver *uvcdp) { + osalDbgCheck(uvcdp != NULL); + memset(uvcdp, 0, sizeof(*uvcdp)); + uvcdp->info = &usbhuvcClassDriverInfo; + chMBObjectInit(&uvcdp->mb, uvcdp->mb_buff, HAL_USBHUVC_MAX_MAILBOX_SZ); + chMtxObjectInit(&uvcdp->mtx); + uvcdp->state = USBHUVC_STATE_STOP; +} + +static void _uvc_init(void) { uint8_t i; for (i = 0; i < HAL_USBHUVC_MAX_INSTANCES; i++) { - usbhuvcObjectInit(&USBHUVCD[i]); + _object_init(&USBHUVCD[i]); } } -- cgit v1.2.3 From 665643c9e47709e6915b22398571be978b59a891 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 19:40:44 -0300 Subject: USBH: list.h reduced to compile only the functions in use --- os/hal/include/usbh/list.h | 323 +++++++++++++++++++++++---------------------- 1 file changed, 162 insertions(+), 161 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/list.h b/os/hal/include/usbh/list.h index 317e51b..1c09b41 100644 --- a/os/hal/include/usbh/list.h +++ b/os/hal/include/usbh/list.h @@ -103,7 +103,7 @@ static inline void __list_del(struct list_head * prev, struct list_head * next) * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ -#ifndef CONFIG_DEBUG_LIST + static inline void __list_del_entry(struct list_head *entry) { __list_del(entry->prev, entry->next); @@ -112,35 +112,6 @@ static inline void __list_del_entry(struct list_head *entry) static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); - // entry->next = LIST_POISON1; - // entry->prev = LIST_POISON2; -} -#else -extern void __list_del_entry(struct list_head *entry); -extern void list_del(struct list_head *entry); -#endif - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * - * If @old was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) -{ - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, - struct list_head *new) -{ - list_replace(old, new); - INIT_LIST_HEAD(old); } /** @@ -154,26 +125,159 @@ static inline void list_del_init(struct list_head *entry) } /** - * list_move - delete from one list and add as another's head + * list_move_tail - delete from one list and add as another's tail * @list: the entry to move - * @head: the head that will precede our entry + * @head: the head that will follow our entry */ -static inline void list_move(struct list_head *list, struct list_head *head) +static inline void list_move_tail(struct list_head *list, + struct list_head *head) { __list_del_entry(list); - list_add(list, head); + list_add_tail(list, head); } + /** - * list_move_tail - delete from one list and add as another's tail + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, type, member) \ + list_entry((pos)->member.next, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, type, head, member) \ + for (pos = list_first_entry(head, type, member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, type, member)) + + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, type, n, head, member) \ + for (pos = list_first_entry(head, type, member), \ + n = list_next_entry(pos, type, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, type, member)) + +#if 0 + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, type, member) \ + list_entry((pos)->member.prev, type, member) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_first_entry_or_null(ptr, type, member) \ + (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) + + +/** + * list_move - delete from one list and add as another's head * @list: the entry to move - * @head: the head that will follow our entry + * @head: the head that will precede our entry */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) +static inline void list_move(struct list_head *list, struct list_head *head) { __list_del_entry(list); - list_add_tail(list, head); + list_add(list, head); } /** @@ -187,15 +291,6 @@ static inline int list_is_last(const struct list_head *list, return list->next == head; } -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - /** * list_empty_careful - tests whether a list is empty and not being modified * @head: the list to test @@ -350,110 +445,28 @@ static inline void list_splice_tail_init(struct list_head *list, } /** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_last_entry - get the last element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_last_entry(ptr, type, member) \ - list_entry((ptr)->prev, type, member) - -/** - * list_first_entry_or_null - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert * - * Note that if the list is empty, it returns NULL. - */ -#define list_first_entry_or_null(ptr, type, member) \ - (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) - -/** - * list_next_entry - get the next element in list - * @pos: the type * to cursor - * @member: the name of the list_head within the struct. - */ -#define list_next_entry(pos, type, member) \ - list_entry((pos)->member.next, type, member) - -/** - * list_prev_entry - get the prev element in list - * @pos: the type * to cursor - * @member: the name of the list_head within the struct. - */ -#define list_prev_entry(pos, type, member) \ - list_entry((pos)->member.prev, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. + * If @old was empty, it will be overwritten. */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} -/** - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_head within the struct. - */ -#define list_for_each_entry(pos, type, head, member) \ - for (pos = list_first_entry(head, type, member); \ - &pos->member != (head); \ - pos = list_next_entry(pos, type, member)) /** * list_for_each_entry_reverse - iterate backwards over list of given type. @@ -517,19 +530,6 @@ static inline void list_splice_tail_init(struct list_head *list, for (; &pos->member != (head); \ pos = list_next_entry(pos, type, member)) -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_head within the struct. - */ -#define list_for_each_entry_safe(pos, type, n, head, member) \ - for (pos = list_first_entry(head, type, member), \ - n = list_next_entry(pos, type, member); \ - &pos->member != (head); \ - pos = n, n = list_next_entry(n, type, member)) - /** * list_for_each_entry_safe_continue - continue list iteration safe against removal * @pos: the type * to use as a loop cursor. @@ -591,5 +591,6 @@ static inline void list_splice_tail_init(struct list_head *list, */ #define list_safe_reset_next(pos, type, n, member) \ n = list_next_entry(pos, type, member) +#endif #endif /* USBH_LIST_H_ */ -- cgit v1.2.3 From 6b7161b90a3572bbb7717d0317306741043528e5 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 19:42:36 -0300 Subject: USBH: moved usbh/desciter.h and usbh/debug.h to usbh/internal.h --- os/hal/include/hal_usbh.h | 7 ------- os/hal/include/usbh/dev/uvc.h | 6 +----- os/hal/include/usbh/internal.h | 3 +++ os/hal/src/usbh/hal_usbh_ftdi.c | 3 --- os/hal/src/usbh/hal_usbh_msd.c | 3 --- os/hal/src/usbh/hal_usbh_uvc.c | 2 +- 6 files changed, 5 insertions(+), 19 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index f6e78e9..d686cfd 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -429,13 +429,6 @@ struct usbh_baseclassdriver { _usbh_base_classdriver_data }; - -/*===========================================================================*/ -/* Helper functions. */ -/*===========================================================================*/ -#include /* descriptor iterators */ -#include /* debug */ - #endif #endif /* HAL_USBH_H_ */ diff --git a/os/hal/include/usbh/dev/uvc.h b/os/hal/include/usbh/dev/uvc.h index bc46a71..817d465 100644 --- a/os/hal/include/usbh/dev/uvc.h +++ b/os/hal/include/usbh/dev/uvc.h @@ -22,11 +22,7 @@ #if HAL_USE_USBH && HAL_USBH_USE_UVC -/* TODO: - * - * - */ - +#include "usbh/desciter.h" /*===========================================================================*/ /* Driver pre-compile time settings. */ diff --git a/os/hal/include/usbh/internal.h b/os/hal/include/usbh/internal.h index 70d2f7a..89695f0 100644 --- a/os/hal/include/usbh/internal.h +++ b/os/hal/include/usbh/internal.h @@ -137,6 +137,9 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status); #define sizeof_array(x) (sizeof(x)/sizeof(*(x))) +#include "usbh/desciter.h" /* descriptor iterators */ +#include "usbh/debug.h" + #endif #endif /* USBH_INTERNAL_H_ */ diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index 9822969..a01c566 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -27,9 +27,6 @@ #include "usbh/dev/ftdi.h" #include "usbh/internal.h" -//#pragma GCC optimize("Og") - - #if USBHFTDI_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index f2a4e39..d631484 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -27,9 +27,6 @@ #include "usbh/dev/msd.h" #include "usbh/internal.h" -//#pragma GCC optimize("Og") - - #if USBHMSD_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index ac3663e..3f362a2 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -27,9 +27,9 @@ #error "USBHUVC needs HAL_USBH_USE_IAD" #endif +#include #include "usbh/dev/uvc.h" #include "usbh/internal.h" -#include #if USBHUVC_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) -- cgit v1.2.3 From 65966b4cd4ff8614df295708d589b0cf2d907ace Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 19:45:57 -0300 Subject: USBH: fixed list.h; should now compile with C++ --- os/hal/include/usbh/list.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/list.h b/os/hal/include/usbh/list.h index 1c09b41..6a02f16 100644 --- a/os/hal/include/usbh/list.h +++ b/os/hal/include/usbh/list.h @@ -42,17 +42,17 @@ static inline void INIT_LIST_HEAD(struct list_head *list) * the prev/next entries already! */ #ifndef CONFIG_DEBUG_LIST -static inline void __list_add(struct list_head *new, +static inline void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; } #else -extern void __list_add(struct list_head *new, +extern void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next); #endif @@ -65,9 +65,9 @@ extern void __list_add(struct list_head *new, * Insert a new entry after the specified head. * This is good for implementing stacks. */ -static inline void list_add(struct list_head *new, struct list_head *head) +static inline void list_add(struct list_head *_new, struct list_head *head) { - __list_add(new, head, head->next); + __list_add(_new, head, head->next); } @@ -79,9 +79,9 @@ static inline void list_add(struct list_head *new, struct list_head *head) * Insert a new entry before the specified head. * This is useful for implementing queues. */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) +static inline void list_add_tail(struct list_head *_new, struct list_head *head) { - __list_add(new, head->prev, head); + __list_add(_new, head->prev, head); } /* @@ -452,18 +452,18 @@ static inline void list_splice_tail_init(struct list_head *list, * If @old was empty, it will be overwritten. */ static inline void list_replace(struct list_head *old, - struct list_head *new) + struct list_head *_new) { - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; + _new->next = old->next; + _new->next->prev = _new; + _new->prev = old->prev; + _new->prev->next = _new; } static inline void list_replace_init(struct list_head *old, - struct list_head *new) + struct list_head *_new) { - list_replace(old, new); + list_replace(old, _new); INIT_LIST_HEAD(old); } -- cgit v1.2.3 From 442b723c127c7e5b808862a50de12d9e49ccf3bf Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 9 Jul 2017 19:49:56 -0300 Subject: USBH: Cleaned up list.h --- os/hal/include/usbh/list.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/list.h b/os/hal/include/usbh/list.h index 6a02f16..cdcca04 100644 --- a/os/hal/include/usbh/list.h +++ b/os/hal/include/usbh/list.h @@ -41,7 +41,6 @@ static inline void INIT_LIST_HEAD(struct list_head *list) * This is only for internal list manipulation where we know * the prev/next entries already! */ -#ifndef CONFIG_DEBUG_LIST static inline void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next) @@ -51,11 +50,6 @@ static inline void __list_add(struct list_head *_new, _new->prev = prev; prev->next = _new; } -#else -extern void __list_add(struct list_head *_new, - struct list_head *prev, - struct list_head *next); -#endif /** * list_add - add a new entry -- cgit v1.2.3 From c9cc2abf3e6854f68a87f72e73cd4eec92262317 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Thu, 13 Jul 2017 12:57:06 -0300 Subject: USBH: cleanup --- os/hal/include/usbh/dev/msd.h | 18 ++---------------- os/hal/src/hal_usbh.c | 9 +-------- os/hal/src/usbh/hal_usbh_hid.c | 3 ++- os/hal/src/usbh/hal_usbh_msd.c | 19 +++++++++++++++++-- 4 files changed, 22 insertions(+), 27 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/dev/msd.h b/os/hal/include/usbh/dev/msd.h index f73836f..3fd2927 100644 --- a/os/hal/include/usbh/dev/msd.h +++ b/os/hal/include/usbh/dev/msd.h @@ -67,19 +67,6 @@ struct USBHMassStorageLUNDriver { USBHMassStorageLUNDriver *next; }; -struct USBHMassStorageDriver { - /* inherited from abstract class driver */ - _usbh_base_classdriver_data - - usbh_ep_t epin; - usbh_ep_t epout; - uint8_t ifnum; - uint8_t max_lun; - uint32_t tag; - - USBHMassStorageLUNDriver *luns; -}; - /*===========================================================================*/ /* Driver macros. */ @@ -91,14 +78,13 @@ struct USBHMassStorageDriver { /*===========================================================================*/ extern USBHMassStorageLUNDriver MSBLKD[HAL_USBHMSD_MAX_LUNS]; -extern USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES]; #ifdef __cplusplus extern "C" { #endif /* Mass Storage LUN Driver (block driver) */ - void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp); - void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp); +// void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp); +// void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp); bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index d0d3cb7..007ef1b 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -20,15 +20,8 @@ #if HAL_USE_USBH #include "usbh/internal.h" -#include - -//devices #include "usbh/dev/hub.h" -#include "usbh/dev/aoa.h" -#include "usbh/dev/ftdi.h" -#include "usbh/dev/msd.h" -#include "usbh/dev/hid.h" -#include "usbh/dev/uvc.h" +#include #if USBH_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index 4b20fd3..5b2823f 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -182,7 +182,8 @@ deinit: } static void _hid_unload(usbh_baseclassdriver_t *drv) { - (void)drv; + USBHHIDDriver *const hidp = (USBHHIDDriver *)drv; + } static void _in_cb(usbh_urb_t *urb) { diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index d631484..f212516 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -65,7 +65,20 @@ static void _lun_object_deinit(USBHMassStorageLUNDriver *lunp); /* USB Class driver loader for MSD */ /*===========================================================================*/ -USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES]; +struct USBHMassStorageDriver { + /* inherited from abstract class driver */ + _usbh_base_classdriver_data + + usbh_ep_t epin; + usbh_ep_t epout; + uint8_t ifnum; + uint8_t max_lun; + uint32_t tag; + + USBHMassStorageLUNDriver *luns; +}; + +static USBHMassStorageDriver USBHMSD[HAL_USBHMSD_MAX_INSTANCES]; static void _msd_init(void); static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); @@ -184,7 +197,7 @@ alloc_ok: MSBLKD[i].next = msdp->luns; msdp->luns = &MSBLKD[i]; MSBLKD[i].msdp = msdp; - MSBLKD[i].state = BLK_ACTIVE; /* transition directly to active, instead of BLK_STOP */ + MSBLKD[i].state = BLK_ACTIVE; luns--; } } @@ -705,6 +718,7 @@ static void _lun_object_init(USBHMassStorageLUNDriver *lunp) { */ } +/* void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); osalSysLock(); @@ -724,6 +738,7 @@ void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp) { //lunp->state = BLK_STOP; osalSysUnlock(); } +*/ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); -- cgit v1.2.3 From c044306ad058689783b1a6941a2a44d5baf738a2 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Thu, 13 Jul 2017 16:45:31 -0300 Subject: USBH: Add flexibility to the enumeration process --- os/hal/include/hal_usbh.h | 3 - os/hal/include/usbh/internal.h | 3 + os/hal/src/hal_usbh.c | 203 +++++++++++++++++++++------------------- os/hal/src/usbh/hal_usbh_aoa.c | 14 +-- os/hal/src/usbh/hal_usbh_ftdi.c | 9 +- os/hal/src/usbh/hal_usbh_hid.c | 7 +- os/hal/src/usbh/hal_usbh_hub.c | 17 ++-- os/hal/src/usbh/hal_usbh_msd.c | 9 +- os/hal/src/usbh/hal_usbh_uvc.c | 5 +- 9 files changed, 134 insertions(+), 136 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index d686cfd..634520c 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -413,9 +413,6 @@ struct usbh_classdriver_vmt { }; struct usbh_classdriverinfo { - int16_t class; - int16_t subclass; - int16_t protocol; const char *name; const usbh_classdriver_vmt_t *vmt; }; diff --git a/os/hal/include/usbh/internal.h b/os/hal/include/usbh/internal.h index 89695f0..f6f17b7 100644 --- a/os/hal/include/usbh/internal.h +++ b/os/hal/include/usbh/internal.h @@ -54,6 +54,9 @@ void _usbh_urb_completeI(usbh_urb_t *urb, usbh_urbstatus_t status); bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status); void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status); +bool _usbh_match_vid_pid(usbh_device_t *dev, int32_t vid, int32_t pid); +bool _usbh_match_descriptor(const uint8_t *descriptor, uint16_t rem, + int16_t type, int16_t _class, int16_t subclass, int16_t protocol); #define USBH_REQTYPE_CLASSIN(type) \ (USBH_REQTYPE_DIR_IN | type | USBH_REQTYPE_TYPE_CLASS) diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index 007ef1b..dad022f 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -56,8 +56,7 @@ #endif static void _classdriver_process_device(usbh_device_t *dev); -static bool _classdriver_load(usbh_device_t *dev, uint8_t class, - uint8_t subclass, uint8_t protocol, uint8_t *descbuff, uint16_t rem); +static bool _classdriver_load(usbh_device_t *dev, uint8_t *descbuff, uint16_t rem); #if HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS #include "usbh_additional_class_drivers.h" @@ -1205,69 +1204,68 @@ void usbhMainLoop(USBHDriver *usbh) { #endif } - /*===========================================================================*/ -/* IAD class driver. */ +/* Class driver loader. */ /*===========================================================================*/ -#if HAL_USBH_USE_IAD -static usbh_baseclassdriver_t *iad_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); -static void iad_unload(usbh_baseclassdriver_t *drv); -static const usbh_classdriver_vmt_t usbhiadClassDriverVMT = { - NULL, - iad_load, - iad_unload -}; -static const usbh_classdriverinfo_t usbhiadClassDriverInfo = { - 0xef, 0x02, 0x01, "IAD", &usbhiadClassDriverVMT -}; -static usbh_baseclassdriver_t *iad_load(usbh_device_t *dev, - const uint8_t *descriptor, uint16_t rem) { - (void)rem; +bool _usbh_match_vid_pid(usbh_device_t *dev, int32_t vid, int32_t pid) { + if (((vid < 0) || (dev->devDesc.idVendor == vid)) + && ((pid < 0) || (dev->devDesc.idProduct == pid))) + return HAL_SUCCESS; - if (descriptor[1] != USBH_DT_DEVICE) - return 0; + return HAL_FAILED; +} - uinfo("Load a driver for each IF collection."); +bool _usbh_match_descriptor(const uint8_t *descriptor, uint16_t rem, + int16_t type, int16_t _class, int16_t subclass, int16_t protocol) { - generic_iterator_t icfg; - if_iterator_t iif; - const usbh_ia_descriptor_t *last_iad = 0; + int16_t dclass, dsubclass, dprotocol; - cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, - dev->basicConfigDesc.wTotalLength); - if (!icfg.valid) { - uerr("Invalid configuration descriptor."); - return 0; - } + if ((rem < descriptor[0]) || (rem < 2)) + return HAL_FAILED; - for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { - if (iif.iad && (iif.iad != last_iad)) { - last_iad = iif.iad; - if (_classdriver_load(dev, iif.iad->bFunctionClass, - iif.iad->bFunctionSubClass, - iif.iad->bFunctionProtocol, - (uint8_t *)iif.iad, - (uint8_t *)iif.curr - (uint8_t *)iif.iad + iif.rem) != HAL_SUCCESS) { - uwarnf("No drivers found for IF collection #%d:%d", - iif.iad->bFirstInterface, - iif.iad->bFirstInterface + iif.iad->bInterfaceCount - 1); - } - } + uint8_t dtype = descriptor[1]; + + if ((type >= 0) && (type != dtype)) + return HAL_FAILED; + + switch (dtype) { + case USBH_DT_DEVICE: { + if (rem < USBH_DT_DEVICE_SIZE) + return HAL_FAILED; + const usbh_device_descriptor_t *const desc = (const usbh_device_descriptor_t *)descriptor; + dclass = desc->bDeviceClass; + dsubclass = desc->bDeviceSubClass; + dprotocol = desc->bDeviceProtocol; + } break; + case USBH_DT_INTERFACE: { + if (rem < USBH_DT_INTERFACE_SIZE) + return HAL_FAILED; + const usbh_interface_descriptor_t *const desc = (const usbh_interface_descriptor_t *)descriptor; + dclass = desc->bInterfaceClass; + dsubclass = desc->bInterfaceSubClass; + dprotocol = desc->bInterfaceProtocol; + } break; + case USBH_DT_INTERFACE_ASSOCIATION: { + if (rem < USBH_DT_INTERFACE_ASSOCIATION_SIZE) + return HAL_FAILED; + const usbh_ia_descriptor_t *const desc = (const usbh_ia_descriptor_t *)descriptor; + dclass = desc->bFunctionClass; + dsubclass = desc->bFunctionSubClass; + dprotocol = desc->bFunctionProtocol; + } break; + default: + return HAL_FAILED; } - return 0; -} + if (((_class < 0) || (_class == dclass)) + && ((subclass < 0) || (subclass == dsubclass)) + && ((protocol < 0) || (protocol == dprotocol))) + return HAL_SUCCESS; -static void iad_unload(usbh_baseclassdriver_t *drv) { - (void)drv; + return HAL_FAILED; } -#endif - -/*===========================================================================*/ -/* Class driver loader. */ -/*===========================================================================*/ static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = { #if HAL_USBH_USE_ADDITIONAL_CLASS_DRIVERS /* user-defined out of tree class drivers */ @@ -1276,8 +1274,8 @@ static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = { #if HAL_USBH_USE_FTDI &usbhftdiClassDriverInfo, #endif -#if HAL_USBH_USE_IAD - &usbhiadClassDriverInfo, +#if HAL_USBH_USE_HUB + &usbhhubClassDriverInfo, #endif #if HAL_USBH_USE_UVC &usbhuvcClassDriverInfo, @@ -1291,44 +1289,24 @@ static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = { #if HAL_USBH_USE_UVC &usbhuvcClassDriverInfo, #endif -#if HAL_USBH_USE_HUB - &usbhhubClassDriverInfo, -#endif #if HAL_USBH_USE_AOA &usbhaoaClassDriverInfo, /* Leave always last */ #endif }; -static bool _classdriver_load(usbh_device_t *dev, uint8_t class, - uint8_t subclass, uint8_t protocol, uint8_t *descbuff, uint16_t rem) { +static bool _classdriver_load(usbh_device_t *dev, uint8_t *descbuff, uint16_t rem) { uint8_t i; usbh_baseclassdriver_t *drv = NULL; for (i = 0; i < sizeof_array(usbh_classdrivers_lookup); i++) { const usbh_classdriverinfo_t *const info = usbh_classdrivers_lookup[i]; - if (class == 0xff) { - /* vendor specific */ - if (info->class == 0xff) { - uinfof("Try load vendor-specific driver %s", info->name); - drv = info->vmt->load(dev, descbuff, rem); - if (drv != NULL) - goto success; - } - } else if ((info->class < 0) || ((info->class == class) - && ((info->subclass < 0) || ((info->subclass == subclass) - && ((info->protocol < 0) || (info->protocol == protocol)))))) { - uinfof("Try load driver %s", info->name); - drv = info->vmt->load(dev, descbuff, rem); -#if HAL_USBH_USE_IAD - /* special case: */ - if (info == &usbhiadClassDriverInfo) - goto success; //return HAL_SUCCESS; -#endif + uinfof("Try load driver %s", info->name); + drv = info->vmt->load(dev, descbuff, rem); - if (drv != NULL) - goto success; - } + if (drv != NULL) + goto success; } + return HAL_FAILED; success: @@ -1369,13 +1347,16 @@ static void _classdriver_process_device(usbh_device_t *dev) { usbhDevicePrintConfiguration(dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); - if (devdesc->bDeviceClass == 0) { - /* each interface defines its own device class/subclass/protocol */ - uinfo("Load a driver for each IF."); +#if HAL_USBH_USE_IAD + if (dev->devDesc.bDeviceClass == 0xef + && dev->devDesc.bDeviceSubClass == 0x02 + && dev->devDesc.bDeviceProtocol == 0x01) { + + uinfo("Load a driver for each IF collection."); generic_iterator_t icfg; if_iterator_t iif; - uint8_t last_if = 0xff; + const usbh_ia_descriptor_t *last_iad = 0; cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, dev->basicConfigDesc.wTotalLength); @@ -1385,24 +1366,49 @@ static void _classdriver_process_device(usbh_device_t *dev) { } for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { - const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); - if (ifdesc->bInterfaceNumber != last_if) { - last_if = ifdesc->bInterfaceNumber; - if (_classdriver_load(dev, ifdesc->bInterfaceClass, - ifdesc->bInterfaceSubClass, - ifdesc->bInterfaceProtocol, - (uint8_t *)ifdesc, iif.rem) != HAL_SUCCESS) { - uwarnf("No drivers found for IF #%d", ifdesc->bInterfaceNumber); + if (iif.iad && (iif.iad != last_iad)) { + last_iad = iif.iad; + if (_classdriver_load(dev, + (uint8_t *)iif.iad, + (uint8_t *)iif.curr - (uint8_t *)iif.iad + iif.rem) != HAL_SUCCESS) { + uwarnf("No drivers found for IF collection #%d:%d", + iif.iad->bFirstInterface, + iif.iad->bFirstInterface + iif.iad->bInterfaceCount - 1); } } } - } else { - if (_classdriver_load(dev, devdesc->bDeviceClass, - devdesc->bDeviceSubClass, - devdesc->bDeviceProtocol, - (uint8_t *)devdesc, USBH_DT_DEVICE_SIZE) != HAL_SUCCESS) { - uwarn("No drivers found."); + } else +#endif + if (_classdriver_load(dev, (uint8_t *)devdesc, USBH_DT_DEVICE_SIZE) != HAL_SUCCESS) { + uinfo("No drivers found for device."); + + if (devdesc->bDeviceClass == 0) { + /* each interface defines its own device class/subclass/protocol */ + uinfo("Try load a driver for each IF."); + + generic_iterator_t icfg; + if_iterator_t iif; + uint8_t last_if = 0xff; + + cfg_iter_init(&icfg, dev->fullConfigurationDescriptor, + dev->basicConfigDesc.wTotalLength); + if (!icfg.valid) { + uerr("Invalid configuration descriptor."); + goto exit; + } + + for (if_iter_init(&iif, &icfg); iif.valid; if_iter_next(&iif)) { + const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); + if (ifdesc->bInterfaceNumber != last_if) { + last_if = ifdesc->bInterfaceNumber; + if (_classdriver_load(dev, (uint8_t *)ifdesc, iif.rem) != HAL_SUCCESS) { + uwarnf("No drivers found for IF #%d", ifdesc->bInterfaceNumber); + } + } + } + } else { + uwarn("Unable to load driver."); } } @@ -1419,6 +1425,7 @@ void usbhInit(void) { usbh_classdrivers_lookup[i]->vmt->init(); } } + usbh_lld_init(); } #endif diff --git a/os/hal/src/usbh/hal_usbh_aoa.c b/os/hal/src/usbh/hal_usbh_aoa.c index db348c0..1526aa3 100644 --- a/os/hal/src/usbh/hal_usbh_aoa.c +++ b/os/hal/src/usbh/hal_usbh_aoa.c @@ -133,7 +133,7 @@ static const usbh_classdriver_vmt_t class_driver_vmt = { }; const usbh_classdriverinfo_t usbhaoaClassDriverInfo = { - 0xff, 0xff, 0xff, "AOA", &class_driver_vmt + "AOA", &class_driver_vmt }; #if defined(HAL_USBHAOA_FILTER_CALLBACK) @@ -146,7 +146,7 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc if (dev->devDesc.idVendor != AOA_GOOGLE_VID) { uint16_t protocol; - static const USBHAOAConfig config = { + static USBHAOAConfig config = { { HAL_USBHAOA_DEFAULT_MANUFACTURER, HAL_USBHAOA_DEFAULT_MODEL, @@ -223,15 +223,9 @@ static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *desc return NULL; } - if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) - return NULL; - const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; - - if ((ifdesc->bInterfaceClass != 0xff) - || (ifdesc->bInterfaceSubClass != 0xff) - || (ifdesc->bInterfaceProtocol != 0x00) - || (ifdesc->bNumEndpoints < 2)) { + if ((_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, 0xFF, 0xFF, 0x00) != HAL_SUCCESS) + || (ifdesc->bNumEndpoints < 2)) { uerr("AOA: This IF is not the Accessory IF"); return NULL; } diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index a01c566..edcf022 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -77,7 +77,7 @@ static const usbh_classdriver_vmt_t class_driver_vmt = { }; const usbh_classdriverinfo_t usbhftdiClassDriverInfo = { - 0xff, 0xff, 0xff, "FTDI", &class_driver_vmt + "FTDI", &class_driver_vmt }; static USBHFTDIPortDriver *_find_port(void) { @@ -93,10 +93,8 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des int i; USBHFTDIDriver *ftdip; - if (dev->devDesc.idVendor != 0x0403) { - uerr("FTDI: Unrecognized VID"); + if (_usbh_match_vid_pid(dev, 0x0403, -1) != HAL_SUCCESS) return NULL; - } switch (dev->devDesc.idProduct) { case 0x6001: @@ -111,7 +109,8 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des return NULL; } - if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) + if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, + 0xff, 0xff, 0xff) != HAL_SUCCESS) return NULL; if (((const usbh_interface_descriptor_t *)descriptor)->bInterfaceNumber != 0) { diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index 5b2823f..269b1b2 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -85,14 +85,15 @@ static const usbh_classdriver_vmt_t class_driver_vmt = { }; const usbh_classdriverinfo_t usbhhidClassDriverInfo = { - 0x03, -1, -1, "HID", &class_driver_vmt + "HID", &class_driver_vmt }; static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) { int i; USBHHIDDriver *hidp; - if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) + if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, + 0x03, -1, -1) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; @@ -183,7 +184,7 @@ deinit: static void _hid_unload(usbh_baseclassdriver_t *drv) { USBHHIDDriver *const hidp = (USBHHIDDriver *)drv; - + (void)hidp; } static void _in_cb(usbh_urb_t *urb) { diff --git a/os/hal/src/usbh/hal_usbh_hub.c b/os/hal/src/usbh/hal_usbh_hub.c index c9bbe9b..80282ef 100644 --- a/os/hal/src/usbh/hal_usbh_hub.c +++ b/os/hal/src/usbh/hal_usbh_hub.c @@ -73,7 +73,7 @@ static const usbh_classdriver_vmt_t usbhhubClassDriverVMT = { }; const usbh_classdriverinfo_t usbhhubClassDriverInfo = { - 0x09, 0x00, -1, "HUB", &usbhhubClassDriverVMT + "HUB", &usbhhubClassDriverVMT }; @@ -146,10 +146,8 @@ static usbh_baseclassdriver_t *_hub_load(usbh_device_t *dev, USBHHubDriver *hubdp; - if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_DEVICE)) - return NULL; - - if (dev->devDesc.bDeviceProtocol != 0) + if (_usbh_match_descriptor(descriptor, rem, USBH_DT_DEVICE, + 0x09, 0x00, 0x00) != HAL_SUCCESS) return NULL; generic_iterator_t iep, icfg; @@ -161,12 +159,10 @@ static usbh_baseclassdriver_t *_hub_load(usbh_device_t *dev, if_iter_init(&iif, &icfg); if (!iif.valid) return NULL; - const usbh_interface_descriptor_t *const ifdesc = if_get(&iif); - if ((ifdesc->bInterfaceClass != 0x09) - || (ifdesc->bInterfaceSubClass != 0x00) - || (ifdesc->bInterfaceProtocol != 0x00)) { + + if (_usbh_match_descriptor(iif.curr, iif.rem, USBH_DT_INTERFACE, + 0x09, 0x00, 0x00) != HAL_SUCCESS) return NULL; - } ep_iter_init(&iep, &iif); if (!iep.valid) @@ -261,6 +257,7 @@ alloc_ok: osalOsRescheduleS(); osalSysUnlock(); + hubdp->dev = NULL; return (usbh_baseclassdriver_t *)hubdp; } diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index f212516..abc58f3 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -91,7 +91,7 @@ static const usbh_classdriver_vmt_t class_driver_vmt = { }; const usbh_classdriverinfo_t usbhmsdClassDriverInfo = { - 0x08, 0x06, 0x50, "MSD", &class_driver_vmt + "MSD", &class_driver_vmt }; #define MSD_REQ_RESET 0xFF @@ -103,15 +103,14 @@ static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *desc uint8_t luns; usbh_urbstatus_t stat; - if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE)) + if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE, + 0x08, 0x06, 0x50) != HAL_SUCCESS) return NULL; const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor; if ((ifdesc->bAlternateSetting != 0) - || (ifdesc->bNumEndpoints < 2) - || (ifdesc->bInterfaceSubClass != 0x06) - || (ifdesc->bInterfaceProtocol != 0x50)) { + || (ifdesc->bNumEndpoints < 2)) { return NULL; } diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index 3f362a2..7777823 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -77,7 +77,7 @@ static const usbh_classdriver_vmt_t class_driver_vmt = { _uvc_unload }; const usbh_classdriverinfo_t usbhuvcClassDriverInfo = { - 0x0e, 0x03, 0x00, "UVC", &class_driver_vmt + "UVC", &class_driver_vmt }; static bool _request(USBHUVCDriver *uvcdp, @@ -518,7 +518,8 @@ static usbh_baseclassdriver_t *_uvc_load(usbh_device_t *dev, const uint8_t *desc USBHUVCDriver *uvcdp; uint8_t i; - if (descriptor[1] != USBH_DT_INTERFACE_ASSOCIATION) + if (_usbh_match_descriptor(descriptor, rem, USBH_DT_INTERFACE_ASSOCIATION, + 0x0e, 0x03, 0x00) != HAL_SUCCESS) return NULL; /* alloc driver */ -- cgit v1.2.3 From 0f269d99fd170929f613b9fa9edcc9af1a5b7c2b Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Fri, 14 Jul 2017 11:01:44 -0300 Subject: USBH: HID: corrected interrupt IN request length --- os/hal/src/usbh/hal_usbh_hid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'os/hal') diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index 269b1b2..6d0e116 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -222,8 +222,11 @@ void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) { hidp->config = cfg; /* init the URBs */ + uint32_t report_len = hidp->epin.wMaxPacketSize; + if (report_len > cfg->report_len) + report_len = cfg->report_len; usbhURBObjectInit(&hidp->in_urb, &hidp->epin, _in_cb, hidp, - cfg->report_buffer, cfg->report_len); + cfg->report_buffer, report_len); /* open the int IN/OUT endpoints */ usbhEPOpen(&hidp->epin); -- cgit v1.2.3 From 3d6f481ba807c85a7e6ee58acbf9b319b1d9a8e2 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Fri, 14 Jul 2017 12:14:59 -0300 Subject: USBH: MSD: replace mutex with semaphores (more lightweight) --- os/hal/include/usbh/dev/msd.h | 2 +- os/hal/src/usbh/hal_usbh_msd.c | 80 +++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 49 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/dev/msd.h b/os/hal/include/usbh/dev/msd.h index 3fd2927..eedd474 100644 --- a/os/hal/include/usbh/dev/msd.h +++ b/os/hal/include/usbh/dev/msd.h @@ -59,7 +59,7 @@ struct USBHMassStorageLUNDriver { _base_block_device_data /* for serializing access to the LUN driver */ - mutex_t mtx; + semaphore_t sem; BlockDeviceInfo info; USBHMassStorageDriver *msdp; diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index abc58f3..d1a5d73 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -695,12 +695,12 @@ static const struct USBHMassStorageDriverVMT blk_vmt = { static void _lun_object_deinit(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); - osalMutexLock(&lunp->mtx); + chSemWait(&lunp->sem); lunp->msdp = NULL; lunp->next = NULL; memset(&lunp->info, 0, sizeof(lunp->info)); lunp->state = BLK_STOP; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); } static void _lun_object_init(USBHMassStorageLUNDriver *lunp) { @@ -708,8 +708,7 @@ static void _lun_object_init(USBHMassStorageLUNDriver *lunp) { memset(lunp, 0, sizeof(*lunp)); lunp->vmt = &blk_vmt; lunp->state = BLK_STOP; - osalMutexObjectInit(&lunp->mtx); - + chSemObjectInit(&lunp->sem, 1); /* Unnecessary because of the memset: lunp->msdp = NULL; lunp->next = NULL; @@ -717,42 +716,20 @@ static void _lun_object_init(USBHMassStorageLUNDriver *lunp) { */ } -/* -void usbhmsdLUNStart(USBHMassStorageLUNDriver *lunp) { - osalDbgCheck(lunp != NULL); - osalSysLock(); - osalDbgAssert((lunp->state == BLK_STOP) || (lunp->state == BLK_ACTIVE), - "invalid state"); - //TODO: complete - //lunp->state = BLK_ACTIVE; - osalSysUnlock(); -} - -void usbhmsdLUNStop(USBHMassStorageLUNDriver *lunp) { - osalDbgCheck(lunp != NULL); - osalSysLock(); - osalDbgAssert((lunp->state == BLK_STOP) || (lunp->state == BLK_ACTIVE), - "invalid state"); - //TODO: complete - //lunp->state = BLK_STOP; - osalSysUnlock(); -} -*/ - bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); osalDbgCheck(lunp->msdp != NULL); msd_result_t res; - osalMutexLock(&lunp->mtx); + osalSysLock(); if (lunp->state == BLK_READY) { - osalMutexUnlock(&lunp->mtx); + osalSysUnlock(); return HAL_SUCCESS; - } else if (lunp->state != BLK_ACTIVE) { - osalMutexUnlock(&lunp->mtx); - return HAL_FAILED; } + chSemWaitS(&lunp->sem); + osalDbgAssert((lunp->state == BLK_ACTIVE), "invalid state"); lunp->state = BLK_CONNECTING; + osalSysUnlock(); { USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq); @@ -820,13 +797,13 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { uinfo("MSD Connected."); lunp->state = BLK_READY; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return HAL_SUCCESS; /* Connection failed, state reset to BLK_ACTIVE.*/ failed: lunp->state = BLK_ACTIVE; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return HAL_FAILED; } @@ -834,20 +811,20 @@ failed: bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); - osalMutexLock(&lunp->mtx); - osalDbgAssert((lunp->state == BLK_ACTIVE) || (lunp->state == BLK_READY), - "invalid state"); - + osalSysLock(); if (lunp->state == BLK_ACTIVE) { - osalMutexUnlock(&lunp->mtx); + osalSysUnlock(); return HAL_SUCCESS; } + chSemWaitS(&lunp->sem); + osalDbgAssert((lunp->state == BLK_READY), "invalid state"); lunp->state = BLK_DISCONNECTING; + osalSysUnlock(); - //TODO: complete + //TODO: complete: sync, etc. lunp->state = BLK_ACTIVE; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return HAL_SUCCESS; } @@ -861,9 +838,9 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, msd_result_t res; uint32_t actual_len; - osalMutexLock(&lunp->mtx); + chSemWait(&lunp->sem); if (lunp->state != BLK_READY) { - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return ret; } lunp->state = BLK_READING; @@ -893,7 +870,7 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk, exit: lunp->state = BLK_READY; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return ret; } @@ -906,9 +883,9 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk, msd_result_t res; uint32_t actual_len; - osalMutexLock(&lunp->mtx); + chSemWait(&lunp->sem); if (lunp->state != BLK_READY) { - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return ret; } lunp->state = BLK_WRITING; @@ -938,7 +915,7 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk, exit: lunp->state = BLK_READY; - osalMutexUnlock(&lunp->mtx); + chSemSignal(&lunp->sem); return ret; } @@ -952,8 +929,15 @@ bool usbhmsdLUNSync(USBHMassStorageLUNDriver *lunp) { bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip) { osalDbgCheck(lunp != NULL); osalDbgCheck(bdip != NULL); - *bdip = lunp->info; - return HAL_SUCCESS; + + osalSysLock(); + if (lunp->state >= BLK_READY) { + *bdip = lunp->info; + osalSysUnlock(); + return HAL_SUCCESS; + } + osalSysUnlock(); + return HAL_FAILED; } bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp) { -- cgit v1.2.3 From b916519dd6d13f4d4d20ece8b646dde480730695 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Fri, 14 Jul 2017 12:15:19 -0300 Subject: USBH: Added TODO list --- os/hal/src/usbh/TODO.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 os/hal/src/usbh/TODO.txt (limited to 'os/hal') diff --git a/os/hal/src/usbh/TODO.txt b/os/hal/src/usbh/TODO.txt new file mode 100644 index 0000000..4d9d1bb --- /dev/null +++ b/os/hal/src/usbh/TODO.txt @@ -0,0 +1,14 @@ +In decreasing order of priority: + +Bugs: +- Synchronization on driver unload between usbhMainLoop and driver APIs + +Enhancements: +- Way to return error from the load() functions in order to stop the enumeration process +- Event sources from the low-level driver, in order to know when to call usbhMainLoop (from the low-level driver and from the HUB driver status callback) +- Possibility of internal main loop +- Linked list for drivers for dynamic registration +- A way to automate matching (similar to linux) +- Hooks to override driver loading and to inform the user of problems + + -- cgit v1.2.3 From 4026bc900dbd33545df5b5bce4cc132d90f84edc Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:19:06 -0300 Subject: USBH: Correct bug in LLD --- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal') diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index a949847..850f9ed 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -668,7 +668,7 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { } /* This URB is active, we can cancel it now */ - uinfof("\t%s: usbh_lld_urb_abort: URB is not active", hcm->ep->name); + uinfof("\t%s: usbh_lld_urb_abort: URB is not active", ep->name); _transfer_completedI(ep, urb, status); return TRUE; -- cgit v1.2.3 From b294a6cff6a58a4788c80cc955aa5e3132052e8b Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:30:13 -0300 Subject: USBH: Use configured UART for debug; avoid garbage debug output --- os/hal/src/usbh/hal_usbh_debug.c | 73 +++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 34 deletions(-) (limited to 'os/hal') diff --git a/os/hal/src/usbh/hal_usbh_debug.c b/os/hal/src/usbh/hal_usbh_debug.c index 7c4ff7d..df773e1 100644 --- a/os/hal/src/usbh/hal_usbh_debug.c +++ b/os/hal/src/usbh/hal_usbh_debug.c @@ -106,17 +106,18 @@ static char *ftoa(char *p, double num, unsigned long precision, bool dot) { } #endif -static inline void _put(char c) { - input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; - - if (iqIsFullI(iqp)) - return; - - iqp->q_counter++; +static inline void _wr(input_queue_t *iqp, char c) { *iqp->q_wrptr++ = c; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; +} +static inline void _put(char c) { + input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; + if (sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter <= 1) + return; + iqp->q_counter++; + _wr(iqp, c); } int _dbg_printf(const char *fmt, va_list ap) { @@ -361,10 +362,15 @@ void usbDbgPrintf(const char *fmt, ...) va_list ap; va_start(ap, fmt); syssts_t sts = chSysGetStatusAndLockX(); - _print_hdr(); - _dbg_printf(fmt, ap); - _put(0); - chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); + input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; + int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter; + if (rem >= 9) { + _print_hdr(); + _dbg_printf(fmt, ap); + iqp->q_counter++; + _wr(iqp, 0); + chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); + } chSysRestoreStatusX(sts); va_end(ap); } @@ -382,22 +388,21 @@ void usbDbgPuts(const char *s) syssts_t sts = chSysGetStatusAndLockX(); input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter; - while (rem) { - *iqp->q_wrptr++ = *p; - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - rem--; - if (++p == top) break; - } - while (rem) { - *iqp->q_wrptr++ = *s; - if (iqp->q_wrptr >= iqp->q_top) - iqp->q_wrptr = iqp->q_buffer; - rem--; - if (!*s++) break; + if (rem >= 9) { + while (rem) { + _wr(iqp, *p); + if (++p == top) break; + } + rem -= 9; + while (rem && *s) { + _wr(iqp, *s); + rem--; + s++; + } + _wr(iqp, 0); + iqp->q_counter = sizeof(USBH_DEBUG_USBHD.dbg_buff) - rem; + chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); } - iqp->q_counter = sizeof(USBH_DEBUG_USBHD.dbg_buff) - rem; - chThdDequeueNextI(&USBH_DEBUG_USBHD.iq.q_waiting, Q_OK); chSysRestoreStatusX(sts); } @@ -429,8 +434,8 @@ void usbDbgSystemHalted(void) { if (!((bool)((USBH_DEBUG_SD.oqueue.q_wrptr == USBH_DEBUG_SD.oqueue.q_rdptr) && (USBH_DEBUG_SD.oqueue.q_counter != 0U)))) break; USBH_DEBUG_SD.oqueue.q_counter++; - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = *USBH_DEBUG_SD.oqueue.q_rdptr++; + while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); + USBH_DEBUG_SD.usart->DR = *USBH_DEBUG_SD.oqueue.q_rdptr++; if (USBH_DEBUG_SD.oqueue.q_rdptr >= USBH_DEBUG_SD.oqueue.q_top) { USBH_DEBUG_SD.oqueue.q_rdptr = USBH_DEBUG_SD.oqueue.q_buffer; } @@ -456,15 +461,15 @@ void usbDbgSystemHalted(void) { while (true) { c = _get(); if (c < 0) return; if (!c) { - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = '\r'; - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = '\n'; + while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); + USBH_DEBUG_SD.usart->DR = '\r'; + while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); + USBH_DEBUG_SD.usart->DR = '\n'; state = 0; break; } - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = c; + while (!(USBH_DEBUG_SD.usart->SR & USART_SR_TXE)); + USBH_DEBUG_SD.usart->DR = c; } } } -- cgit v1.2.3 From 54c53d4e22ebce803a111e3c80ddd1796bb37c07 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:32:23 -0300 Subject: USBH: MSD: improved syncrhonization --- os/hal/src/usbh/hal_usbh_msd.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'os/hal') diff --git a/os/hal/src/usbh/hal_usbh_msd.c b/os/hal/src/usbh/hal_usbh_msd.c index d1a5d73..069c47b 100644 --- a/os/hal/src/usbh/hal_usbh_msd.c +++ b/os/hal/src/usbh/hal_usbh_msd.c @@ -721,15 +721,13 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp->msdp != NULL); msd_result_t res; - osalSysLock(); + chSemWait(&lunp->sem); + osalDbgAssert((lunp->state == BLK_READY) || (lunp->state == BLK_ACTIVE), "invalid state"); if (lunp->state == BLK_READY) { - osalSysUnlock(); + chSemSignal(&lunp->sem); return HAL_SUCCESS; } - chSemWaitS(&lunp->sem); - osalDbgAssert((lunp->state == BLK_ACTIVE), "invalid state"); lunp->state = BLK_CONNECTING; - osalSysUnlock(); { USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq); @@ -795,31 +793,28 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) { (uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL))); uinfo("MSD Connected."); - lunp->state = BLK_READY; chSemSignal(&lunp->sem); return HAL_SUCCESS; /* Connection failed, state reset to BLK_ACTIVE.*/ failed: + uinfo("MSD Connect failed."); lunp->state = BLK_ACTIVE; chSemSignal(&lunp->sem); return HAL_FAILED; } - bool usbhmsdLUNDisconnect(USBHMassStorageLUNDriver *lunp) { osalDbgCheck(lunp != NULL); - osalSysLock(); + chSemWait(&lunp->sem); + osalDbgAssert((lunp->state == BLK_READY) || (lunp->state == BLK_ACTIVE), "invalid state"); if (lunp->state == BLK_ACTIVE) { - osalSysUnlock(); + chSemSignal(&lunp->sem); return HAL_SUCCESS; } - chSemWaitS(&lunp->sem); - osalDbgAssert((lunp->state == BLK_READY), "invalid state"); lunp->state = BLK_DISCONNECTING; - osalSysUnlock(); //TODO: complete: sync, etc. -- cgit v1.2.3 From d395dde065b77506a0883918af4bd48005e5df7c Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:34:19 -0300 Subject: USBH: HUB: don't clear status flags on NAK --- os/hal/src/usbh/hal_usbh_hub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'os/hal') diff --git a/os/hal/src/usbh/hal_usbh_hub.c b/os/hal/src/usbh/hal_usbh_hub.c index 80282ef..f9b6418 100644 --- a/os/hal/src/usbh/hal_usbh_hub.c +++ b/os/hal/src/usbh/hal_usbh_hub.c @@ -107,7 +107,7 @@ static void _urb_complete(usbh_urb_t *urb) { case USBH_URBSTATUS_TIMEOUT: /* the device NAKed */ udbg("HUB: no info"); - hubdp->statuschange = 0; + //hubdp->statuschange = 0; break; case USBH_URBSTATUS_OK: { uint8_t len = hubdp->hubDesc.bNbrPorts / 8 + 1; @@ -266,9 +266,7 @@ static void _hub_unload(usbh_baseclassdriver_t *drv) { USBHHubDriver *const hubdp = (USBHHubDriver *)drv; /* close the status change endpoint (this cancels ongoing URBs) */ - osalSysLock(); - usbhEPCloseS(&hubdp->epint); - osalSysUnlock(); + usbhEPClose(&hubdp->epint); /* de-alloc ports and unload drivers */ usbh_port_t *port = hubdp->ports; -- cgit v1.2.3 From 7bf4908f231061ab909c086722ead46dd7df87f9 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:38:59 -0300 Subject: USBH: HID: Implement synchronization --- os/hal/include/usbh/dev/hid.h | 2 ++ os/hal/src/usbh/TODO.txt | 7 +++++++ os/hal/src/usbh/hal_usbh_hid.c | 39 +++++++++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 14 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/usbh/dev/hid.h b/os/hal/include/usbh/dev/hid.h index 1dbc486..c7371ee 100644 --- a/os/hal/include/usbh/dev/hid.h +++ b/os/hal/include/usbh/dev/hid.h @@ -95,6 +95,8 @@ struct USBHHIDDriver { usbh_urb_t in_urb; const USBHHIDConfig *config; + + semaphore_t sem; }; diff --git a/os/hal/src/usbh/TODO.txt b/os/hal/src/usbh/TODO.txt index 4d9d1bb..c3dd4a8 100644 --- a/os/hal/src/usbh/TODO.txt +++ b/os/hal/src/usbh/TODO.txt @@ -2,6 +2,13 @@ In decreasing order of priority: Bugs: - Synchronization on driver unload between usbhMainLoop and driver APIs + - MSD: ok + - AOA: not done + - HUB: ok + - FTDI: not done + - HID: ok + - UVC: not done + Enhancements: - Way to return error from the load() functions in order to stop the enumeration process diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index 6d0e116..575b0a6 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -69,7 +69,7 @@ #define USBH_HID_REQ_SET_PROTOCOL 0x0B /*===========================================================================*/ -/* USB Class driver loader for MSD */ +/* USB Class driver loader for HID */ /*===========================================================================*/ USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES]; @@ -77,6 +77,7 @@ USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES]; static void _hid_init(void); static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem); static void _hid_unload(usbh_baseclassdriver_t *drv); +static void _stop_locked(USBHHIDDriver *hidp); static const usbh_classdriver_vmt_t class_driver_vmt = { _hid_init, @@ -184,7 +185,10 @@ deinit: static void _hid_unload(usbh_baseclassdriver_t *drv) { USBHHIDDriver *const hidp = (USBHHIDDriver *)drv; - (void)hidp; + chSemWait(&hidp->sem); + _stop_locked(hidp); + hidp->state = USBHHID_STATE_STOP; + chSemSignal(&hidp->sem); } static void _in_cb(usbh_urb_t *urb) { @@ -213,11 +217,13 @@ static void _in_cb(usbh_urb_t *urb) { void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) { osalDbgCheck(hidp && cfg); osalDbgCheck(cfg->report_buffer && (cfg->protocol <= USBHHID_PROTOCOL_REPORT)); - osalDbgCheck((hidp->state == USBHHID_STATE_ACTIVE) - || (hidp->state == USBHHID_STATE_READY)); - if (hidp->state == USBHHID_STATE_READY) + chSemWait(&hidp->sem); + if (hidp->state == USBHHID_STATE_READY) { + chSemSignal(&hidp->sem); return; + } + osalDbgCheck(hidp->state == USBHHID_STATE_ACTIVE); hidp->config = cfg; @@ -243,24 +249,28 @@ void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) { osalSysUnlock(); hidp->state = USBHHID_STATE_READY; + chSemSignal(&hidp->sem); } -void usbhhidStop(USBHHIDDriver *hidp) { - osalDbgCheck((hidp->state == USBHHID_STATE_ACTIVE) - || (hidp->state == USBHHID_STATE_READY)); - - if (hidp->state != USBHHID_STATE_READY) +static void _stop_locked(USBHHIDDriver *hidp) { + if (hidp->state == USBHHID_STATE_ACTIVE) return; - osalSysLock(); - usbhEPCloseS(&hidp->epin); + osalDbgCheck(hidp->state == USBHHID_STATE_READY); + + usbhEPClose(&hidp->epin); #if HAL_USBHHID_USE_INTERRUPT_OUT if (hidp->epout.status != USBH_EPSTATUS_UNINITIALIZED) { - usbhEPCloseS(&hidp->epout); + usbhEPClose(&hidp->epout); } #endif hidp->state = USBHHID_STATE_ACTIVE; - osalSysUnlock(); +} + +void usbhhidStop(USBHHIDDriver *hidp) { + chSemWait(&hidp->sem); + _stop_locked(hidp); + chSemSignal(&hidp->sem); } usbh_urbstatus_t usbhhidGetReport(USBHHIDDriver *hidp, @@ -317,6 +327,7 @@ static void _hid_object_init(USBHHIDDriver *hidp) { memset(hidp, 0, sizeof(*hidp)); hidp->info = &usbhhidClassDriverInfo; hidp->state = USBHHID_STATE_STOP; + chSemObjectInit(&hidp->sem, 1); } static void _hid_init(void) { -- cgit v1.2.3 From ce8f18291fb45048685be52bcff5088b14a6823c Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 18:40:09 -0300 Subject: USBH: Use infinite timeout for control request, when timeouts are not specified --- os/hal/src/hal_usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal') diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index dad022f..d72ab8c 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -427,7 +427,7 @@ usbh_urbstatus_t usbhControlRequest(usbh_device_t *dev, wIndex, wLength }; - return usbhControlRequestExtended(dev, &req, buff, NULL, MS2ST(1000)); + return usbhControlRequestExtended(dev, &req, buff, NULL, TIME_INFINITE); } /*===========================================================================*/ -- cgit v1.2.3 From dee22cee18dd98502b19e41e45503f8c20f447d6 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 20:01:50 -0300 Subject: USBH: remove unnecessary reschedules and add necessary ones --- os/hal/include/hal_usbh.h | 20 +++++++++++++++++--- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 8 +------- os/hal/src/hal_usbh.c | 12 +++++++----- os/hal/src/usbh/TODO.txt | 2 +- os/hal/src/usbh/hal_usbh_aoa.c | 7 ++----- os/hal/src/usbh/hal_usbh_ftdi.c | 7 ++----- os/hal/src/usbh/hal_usbh_hid.c | 4 +--- os/hal/src/usbh/hal_usbh_hub.c | 5 +---- os/hal/src/usbh/hal_usbh_uvc.c | 8 +++----- 9 files changed, 35 insertions(+), 38 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index 634520c..3e69607 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -358,10 +358,8 @@ extern "C" { osalDbgCheck(ep != 0); osalDbgCheckClassS(); osalDbgAssert(ep->status != USBH_EPSTATUS_UNINITIALIZED, "invalid state"); - if (ep->status == USBH_EPSTATUS_CLOSED) { - osalOsRescheduleS(); + if (ep->status == USBH_EPSTATUS_CLOSED) return; - } usbh_lld_ep_close(ep); } static inline void usbhEPClose(usbh_ep_t *ep) { @@ -392,6 +390,22 @@ extern "C" { void usbhURBCancelAndWaitS(usbh_urb_t *urb); msg_t usbhURBWaitTimeoutS(usbh_urb_t *urb, systime_t timeout); + static inline void usbhURBSubmit(usbh_urb_t *urb) { + osalSysLock(); + usbhURBSubmitI(urb); + osalOsRescheduleS(); + osalSysUnlock(); + } + + static inline bool usbhURBCancel(usbh_urb_t *urb) { + bool ret; + osalSysLock(); + ret = usbhURBCancelI(urb); + osalOsRescheduleS(); + osalSysUnlock(); + return ret; + } + /* Main loop */ void usbhMainLoop(USBHDriver *usbh); diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index 850f9ed..3a581f5 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -602,7 +602,6 @@ void usbh_lld_ep_object_init(usbh_ep_t *ep) { void usbh_lld_ep_open(usbh_ep_t *ep) { uinfof("\t%s: Open EP", ep->name); ep->status = USBH_EPSTATUS_OPEN; - osalOsRescheduleS(); } void usbh_lld_ep_close(usbh_ep_t *ep) { @@ -614,7 +613,6 @@ void usbh_lld_ep_close(usbh_ep_t *ep) { } uinfof("\t%s: Closed", ep->name); ep->status = USBH_EPSTATUS_CLOSED; - osalOsRescheduleS(); } bool usbh_lld_ep_reset(usbh_ep_t *ep) { @@ -643,6 +641,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) { } } +/* usbh_lld_urb_abort may require a reschedule if called from a S-locked state */ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheck(usbhURBIsBusy(urb)); @@ -1594,7 +1593,6 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy osalDbgAssert(0, "invalid wvalue"); break; } - osalOsRescheduleS(); osalSysUnlock(); break; @@ -1623,7 +1621,6 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy osalDbgCheck(wlength >= 4); osalSysLock(); *(uint32_t *)buf = usbh->rootport.lld_status | (usbh->rootport.lld_c_status << 16); - osalOsRescheduleS(); osalSysUnlock(); break; @@ -1653,7 +1650,6 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy osalThreadSleepS(MS2ST(60)); otg->HPRT = hprt; usbh->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET; - osalOsRescheduleS(); osalSysUnlock(); } break; @@ -1678,11 +1674,9 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh) { osalSysLock(); if (usbh->rootport.lld_c_status) { - osalOsRescheduleS(); osalSysUnlock(); return 1 << 1; } - osalOsRescheduleS(); osalSysUnlock(); return 0; } diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index d72ab8c..1aa35d0 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -111,7 +111,6 @@ void usbhStart(USBHDriver *usbh) { "invalid state"); usbh_lld_start(usbh); usbh->status = USBH_STATUS_STARTED; - osalOsRescheduleS(); osalSysUnlock(); } @@ -224,6 +223,7 @@ void usbhURBObjectResetI(usbh_urb_t *urb) { usbh_lld_urb_object_reset(urb); } +/* usbhURBSubmitI may require a reschedule if called from a S-locked state */ void usbhURBSubmitI(usbh_urb_t *urb) { osalDbgCheckClassI(); _check_urb(urb); @@ -245,6 +245,7 @@ void usbhURBSubmitI(usbh_urb_t *urb) { usbh_lld_urb_submit(urb); } +/* _usbh_urb_abortI may require a reschedule if called from a S-locked state */ bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheckClassI(); _check_urb(urb); @@ -280,15 +281,18 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status) { } #if !(USBH_DEBUG_ENABLE && USBH_DEBUG_ENABLE_WARNINGS) else { + /* This call is necessary because _usbh_urb_abortI may require a reschedule */ osalOsRescheduleS(); } #else uwarn("URB aborted"); osalOsRescheduleS(); /* debug printing functions call I-class functions inside - which may cause a priority violation without this call */ + which may cause a priority violation without this call + Also, _usbh_urb_abortI may require a reschedule */ #endif } +/* usbhURBCancelI may require a reschedule if called from a S-locked state */ bool usbhURBCancelI(usbh_urb_t *urb) { return _usbh_urb_abortI(urb, USBH_URBSTATUS_CANCELLED); } @@ -313,7 +317,6 @@ msg_t usbhURBWaitTimeoutS(usbh_urb_t *urb, systime_t timeout) { case USBH_URBSTATUS_OK: ret = MSG_OK; - osalOsRescheduleS(); break; /* case USBH_URBSTATUS_UNINITIALIZED: @@ -324,7 +327,6 @@ msg_t usbhURBWaitTimeoutS(usbh_urb_t *urb, systime_t timeout) { * case USBH_URBSTATUS_DISCONNECTED: */ default: ret = MSG_RESET; - osalOsRescheduleS(); break; } return ret; @@ -350,6 +352,7 @@ static inline msg_t _wakeup_message(usbh_urbstatus_t status) { return MSG_RESET; } +/* _usbh_urb_completeI may require a reschedule if called from a S-locked state */ void _usbh_urb_completeI(usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheckClassI(); _check_urb(urb); @@ -1128,7 +1131,6 @@ static uint32_t _hub_get_status_change_bitmap(USBHDriver *host, USBHHubDriver *h osalSysLock(); uint32_t ret = hub->statuschange; hub->statuschange = 0; - osalOsRescheduleS(); osalSysUnlock(); return ret; } diff --git a/os/hal/src/usbh/TODO.txt b/os/hal/src/usbh/TODO.txt index c3dd4a8..532420b 100644 --- a/os/hal/src/usbh/TODO.txt +++ b/os/hal/src/usbh/TODO.txt @@ -17,5 +17,5 @@ Enhancements: - Linked list for drivers for dynamic registration - A way to automate matching (similar to linux) - Hooks to override driver loading and to inform the user of problems - +- for STM32 LLD: think of a way to prevent Bulk IN NAK interrupt flood. diff --git a/os/hal/src/usbh/hal_usbh_aoa.c b/os/hal/src/usbh/hal_usbh_aoa.c index 1526aa3..b8e37ae 100644 --- a/os/hal/src/usbh/hal_usbh_aoa.c +++ b/os/hal/src/usbh/hal_usbh_aoa.c @@ -295,7 +295,6 @@ static void _aoa_unload(usbh_baseclassdriver_t *drv) { _stop_channelS(&aoap->channel); aoap->channel.state = USBHAOA_CHANNEL_STATE_STOP; aoap->state = USBHAOA_STATE_STOP; - osalOsRescheduleS(); osalSysUnlock(); } @@ -521,6 +520,7 @@ static void _stop_channelS(USBHAOAChannel *aoacp) { chThdDequeueAllI(&aoacp->oq_waiting, Q_RESET); chnAddFlagsI(aoacp, CHN_DISCONNECTED); aoacp->state = USBHAOA_CHANNEL_STATE_ACTIVE; + osalOsRescheduleS(); } static void _vt(void *p) { @@ -562,9 +562,7 @@ void usbhaoaChannelStart(USBHAOADriver *aoap) { aoacp->iq_counter = 0; aoacp->iq_ptr = aoacp->iq_buff; usbhEPOpen(&aoacp->epin); - osalSysLock(); - usbhURBSubmitI(&aoacp->iq_urb); - osalSysUnlock(); + usbhURBSubmit(&aoacp->iq_urb); chVTObjectInit(&aoacp->vt); chVTSet(&aoacp->vt, MS2ST(16), _vt, aoacp); @@ -579,7 +577,6 @@ void usbhaoaChannelStop(USBHAOADriver *aoap) { || (aoap->channel.state == USBHAOA_CHANNEL_STATE_READY)); osalSysLock(); _stop_channelS(&aoap->channel); - osalOsRescheduleS(); osalSysUnlock(); } diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index edcf022..2e9f506 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -219,7 +219,6 @@ static void _ftdi_unload(usbh_baseclassdriver_t *drv) { while (ftdipp) { osalSysLock(); _stopS(ftdipp); - osalOsRescheduleS(); osalSysUnlock(); ftdipp = ftdipp->next; } @@ -636,6 +635,7 @@ static void _stopS(USBHFTDIPortDriver *ftdipp) { chThdDequeueAllI(&ftdipp->iq_waiting, Q_RESET); chThdDequeueAllI(&ftdipp->oq_waiting, Q_RESET); ftdipp->state = USBHFTDIP_STATE_ACTIVE; + osalOsRescheduleS(); } void usbhftdipStop(USBHFTDIPortDriver *ftdipp) { @@ -646,7 +646,6 @@ void usbhftdipStop(USBHFTDIPortDriver *ftdipp) { chMtxLockS(&ftdipp->ftdip->mtx); _stopS(ftdipp); chMtxUnlockS(&ftdipp->ftdip->mtx); - osalOsRescheduleS(); osalSysUnlock(); } @@ -688,9 +687,7 @@ void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config ftdipp->iq_counter = 0; ftdipp->iq_ptr = ftdipp->iq_buff; usbhEPOpen(&ftdipp->epin); - osalSysLock(); - usbhURBSubmitI(&ftdipp->iq_urb); - osalSysUnlock(); + usbhURBSubmit(&ftdipp->iq_urb); chVTObjectInit(&ftdipp->vt); chVTSet(&ftdipp->vt, MS2ST(16), _vt, ftdipp); diff --git a/os/hal/src/usbh/hal_usbh_hid.c b/os/hal/src/usbh/hal_usbh_hid.c index 575b0a6..2b2c5ce 100644 --- a/os/hal/src/usbh/hal_usbh_hid.c +++ b/os/hal/src/usbh/hal_usbh_hid.c @@ -244,9 +244,7 @@ void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) { usbhhidSetProtocol(hidp, cfg->protocol); - osalSysLock(); - usbhURBSubmitI(&hidp->in_urb); - osalSysUnlock(); + usbhURBSubmit(&hidp->in_urb); hidp->state = USBHHID_STATE_READY; chSemSignal(&hidp->sem); diff --git a/os/hal/src/usbh/hal_usbh_hub.c b/os/hal/src/usbh/hal_usbh_hub.c index f9b6418..6a83c66 100644 --- a/os/hal/src/usbh/hal_usbh_hub.c +++ b/os/hal/src/usbh/hal_usbh_hub.c @@ -252,10 +252,7 @@ alloc_ok: _urb_complete, hubdp, hubdp->scbuff, (hubdesc->bNbrPorts + 8) / 8); - osalSysLock(); - usbhURBSubmitI(&hubdp->urb); - osalOsRescheduleS(); - osalSysUnlock(); + usbhURBSubmit(&hubdp->urb); hubdp->dev = NULL; return (usbh_baseclassdriver_t *)hubdp; diff --git a/os/hal/src/usbh/hal_usbh_uvc.c b/os/hal/src/usbh/hal_usbh_uvc.c index 7777823..a795cd8 100644 --- a/os/hal/src/usbh/hal_usbh_uvc.c +++ b/os/hal/src/usbh/hal_usbh_uvc.c @@ -361,10 +361,8 @@ bool usbhuvcStreamStart(USBHUVCDriver *uvcdp, uint16_t min_ep_sz) { osalDbgCheck(msg); usbhURBObjectInit(&uvcdp->urb_iso, &uvcdp->ep_iso, _cb_iso, uvcdp, msg->data, uvcdp->ep_iso.wMaxPacketSize); } - osalSysLock(); - usbhURBSubmitI(&uvcdp->urb_iso); - osalOsRescheduleS(); - osalSysUnlock(); + + usbhURBSubmit(&uvcdp->urb_iso); ret = HAL_SUCCESS; goto exit; @@ -695,7 +693,7 @@ alloc_ok: osalSysLock(); usbhURBSubmitI(&uvcdp->urb_int); uvcdp->state = USBHUVC_STATE_ACTIVE; - osalOsRescheduleS(); + osalOsRescheduleS(); /* because of usbhURBSubmitI */ osalSysUnlock(); dev->keepFullCfgDesc++; -- cgit v1.2.3 From 91fd21695b3030e5785b4bd90655fd6f54925abe Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Sun, 16 Jul 2017 20:08:02 -0300 Subject: USBH: replaced some ch* functions with OSAL equivalents --- os/hal/src/usbh/hal_usbh_aoa.c | 48 ++++++++++++++++++++--------------------- os/hal/src/usbh/hal_usbh_ftdi.c | 48 ++++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 48 deletions(-) (limited to 'os/hal') diff --git a/os/hal/src/usbh/hal_usbh_aoa.c b/os/hal/src/usbh/hal_usbh_aoa.c index b8e37ae..85c3130 100644 --- a/os/hal/src/usbh/hal_usbh_aoa.c +++ b/os/hal/src/usbh/hal_usbh_aoa.c @@ -336,15 +336,15 @@ static size_t _write_timeout(USBHAOAChannel *aoacp, const uint8_t *bp, chDbgCheck(n > 0U); size_t w = 0; - chSysLock(); + osalSysLock(); while (true) { if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return w; } while (usbhURBIsBusy(&aoacp->oq_urb)) { if (chThdEnqueueTimeoutS(&aoacp->oq_waiting, timeout) != Q_OK) { - chSysUnlock(); + osalSysUnlock(); return w; } } @@ -352,30 +352,30 @@ static size_t _write_timeout(USBHAOAChannel *aoacp, const uint8_t *bp, *aoacp->oq_ptr++ = *bp++; if (--aoacp->oq_counter == 0) { _submitOutI(aoacp, 64); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ + osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ w++; if (--n == 0U) return w; - chSysLock(); + osalSysLock(); } } static msg_t _put_timeout(USBHAOAChannel *aoacp, uint8_t b, systime_t timeout) { - chSysLock(); + osalSysLock(); if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return Q_RESET; } while (usbhURBIsBusy(&aoacp->oq_urb)) { msg_t msg = chThdEnqueueTimeoutS(&aoacp->oq_waiting, timeout); if (msg < Q_OK) { - chSysUnlock(); + osalSysUnlock(); return msg; } } @@ -383,9 +383,9 @@ static msg_t _put_timeout(USBHAOAChannel *aoacp, uint8_t b, systime_t timeout) { *aoacp->oq_ptr++ = b; if (--aoacp->oq_counter == 0) { _submitOutI(aoacp, 64); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); return Q_OK; } @@ -434,41 +434,41 @@ static size_t _read_timeout(USBHAOAChannel *aoacp, uint8_t *bp, chDbgCheck(n > 0U); - chSysLock(); + osalSysLock(); while (true) { if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return r; } while (aoacp->iq_counter == 0) { if (!usbhURBIsBusy(&aoacp->iq_urb)) _submitInI(aoacp); if (chThdEnqueueTimeoutS(&aoacp->iq_waiting, timeout) != Q_OK) { - chSysUnlock(); + osalSysUnlock(); return r; } } *bp++ = *aoacp->iq_ptr++; if (--aoacp->iq_counter == 0) { _submitInI(aoacp); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); r++; if (--n == 0U) return r; - chSysLock(); + osalSysLock(); } } static msg_t _get_timeout(USBHAOAChannel *aoacp, systime_t timeout) { uint8_t b; - chSysLock(); + osalSysLock(); if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return Q_RESET; } while (aoacp->iq_counter == 0) { @@ -476,16 +476,16 @@ static msg_t _get_timeout(USBHAOAChannel *aoacp, systime_t timeout) { _submitInI(aoacp); msg_t msg = chThdEnqueueTimeoutS(&aoacp->iq_waiting, timeout); if (msg < Q_OK) { - chSysUnlock(); + osalSysUnlock(); return msg; } } b = *aoacp->iq_ptr++; if (--aoacp->iq_counter == 0) { _submitInI(aoacp); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); return (msg_t)b; } @@ -525,7 +525,7 @@ static void _stop_channelS(USBHAOAChannel *aoacp) { static void _vt(void *p) { USBHAOAChannel *const aoacp = (USBHAOAChannel *)p; - chSysLockFromISR(); + osalSysLockFromISR(); uint32_t len = aoacp->oq_ptr - aoacp->oq_buff; if (len && !usbhURBIsBusy(&aoacp->oq_urb)) { _submitOutI(aoacp, len); @@ -534,7 +534,7 @@ static void _vt(void *p) { _submitInI(aoacp); } chVTSetI(&aoacp->vt, MS2ST(16), _vt, aoacp); - chSysUnlockFromISR(); + osalSysUnlockFromISR(); } void usbhaoaChannelStart(USBHAOADriver *aoap) { diff --git a/os/hal/src/usbh/hal_usbh_ftdi.c b/os/hal/src/usbh/hal_usbh_ftdi.c index 2e9f506..6e33867 100644 --- a/os/hal/src/usbh/hal_usbh_ftdi.c +++ b/os/hal/src/usbh/hal_usbh_ftdi.c @@ -430,15 +430,15 @@ static size_t _write_timeout(USBHFTDIPortDriver *ftdipp, const uint8_t *bp, chDbgCheck(n > 0U); size_t w = 0; - chSysLock(); + osalSysLock(); while (true) { if (ftdipp->state != USBHFTDIP_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return w; } while (usbhURBIsBusy(&ftdipp->oq_urb)) { if (chThdEnqueueTimeoutS(&ftdipp->oq_waiting, timeout) != Q_OK) { - chSysUnlock(); + osalSysUnlock(); return w; } } @@ -446,30 +446,30 @@ static size_t _write_timeout(USBHFTDIPortDriver *ftdipp, const uint8_t *bp, *ftdipp->oq_ptr++ = *bp++; if (--ftdipp->oq_counter == 0) { _submitOutI(ftdipp, 64); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ + osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ w++; if (--n == 0U) return w; - chSysLock(); + osalSysLock(); } } static msg_t _put_timeout(USBHFTDIPortDriver *ftdipp, uint8_t b, systime_t timeout) { - chSysLock(); + osalSysLock(); if (ftdipp->state != USBHFTDIP_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return Q_RESET; } while (usbhURBIsBusy(&ftdipp->oq_urb)) { msg_t msg = chThdEnqueueTimeoutS(&ftdipp->oq_waiting, timeout); if (msg < Q_OK) { - chSysUnlock(); + osalSysUnlock(); return msg; } } @@ -477,9 +477,9 @@ static msg_t _put_timeout(USBHFTDIPortDriver *ftdipp, uint8_t b, systime_t timeo *ftdipp->oq_ptr++ = b; if (--ftdipp->oq_counter == 0) { _submitOutI(ftdipp, 64); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); return Q_OK; } @@ -536,41 +536,41 @@ static size_t _read_timeout(USBHFTDIPortDriver *ftdipp, uint8_t *bp, chDbgCheck(n > 0U); - chSysLock(); + osalSysLock(); while (true) { if (ftdipp->state != USBHFTDIP_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return r; } while (ftdipp->iq_counter == 0) { if (!usbhURBIsBusy(&ftdipp->iq_urb)) _submitInI(ftdipp); if (chThdEnqueueTimeoutS(&ftdipp->iq_waiting, timeout) != Q_OK) { - chSysUnlock(); + osalSysUnlock(); return r; } } *bp++ = *ftdipp->iq_ptr++; if (--ftdipp->iq_counter == 0) { _submitInI(ftdipp); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); r++; if (--n == 0U) return r; - chSysLock(); + osalSysLock(); } } static msg_t _get_timeout(USBHFTDIPortDriver *ftdipp, systime_t timeout) { uint8_t b; - chSysLock(); + osalSysLock(); if (ftdipp->state != USBHFTDIP_STATE_READY) { - chSysUnlock(); + osalSysUnlock(); return Q_RESET; } while (ftdipp->iq_counter == 0) { @@ -578,16 +578,16 @@ static msg_t _get_timeout(USBHFTDIPortDriver *ftdipp, systime_t timeout) { _submitInI(ftdipp); msg_t msg = chThdEnqueueTimeoutS(&ftdipp->iq_waiting, timeout); if (msg < Q_OK) { - chSysUnlock(); + osalSysUnlock(); return msg; } } b = *ftdipp->iq_ptr++; if (--ftdipp->iq_counter == 0) { _submitInI(ftdipp); - chSchRescheduleS(); + osalOsRescheduleS(); } - chSysUnlock(); + osalSysUnlock(); return (msg_t)b; } @@ -602,7 +602,7 @@ static size_t _read(USBHFTDIPortDriver *ftdipp, uint8_t *bp, size_t n) { static void _vt(void *p) { USBHFTDIPortDriver *const ftdipp = (USBHFTDIPortDriver *)p; - chSysLockFromISR(); + osalSysLockFromISR(); uint32_t len = ftdipp->oq_ptr - ftdipp->oq_buff; if (len && !usbhURBIsBusy(&ftdipp->oq_urb)) { _submitOutI(ftdipp, len); @@ -611,7 +611,7 @@ static void _vt(void *p) { _submitInI(ftdipp); } chVTSetI(&ftdipp->vt, MS2ST(16), _vt, ftdipp); - chSysUnlockFromISR(); + osalSysUnlockFromISR(); } static const struct FTDIPortDriverVMT async_channel_vmt = { -- cgit v1.2.3 From 2fb4cf92737dae0fbcea90939e4af5b534eb35d6 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 31 Jul 2017 18:38:46 -0300 Subject: USBH: improved main driver - improved connection/disconnection handling - corrected bug on aborting non-pending URB - corrected bug on disconnecting multiple hubs - improved debug messages --- os/hal/src/hal_usbh.c | 105 ++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 47 deletions(-) (limited to 'os/hal') diff --git a/os/hal/src/hal_usbh.c b/os/hal/src/hal_usbh.c index 1aa35d0..a7ba236 100644 --- a/os/hal/src/hal_usbh.c +++ b/os/hal/src/hal_usbh.c @@ -249,24 +249,17 @@ void usbhURBSubmitI(usbh_urb_t *urb) { bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheckClassI(); _check_urb(urb); + osalDbgCheck(urb->status != USBH_URBSTATUS_UNINITIALIZED); - switch (urb->status) { -/* case USBH_URBSTATUS_UNINITIALIZED: - * case USBH_URBSTATUS_INITIALIZED: - * case USBH_URBSTATUS_ERROR: - * case USBH_URBSTATUS_TIMEOUT: - * case USBH_URBSTATUS_CANCELLED: - * case USBH_URBSTATUS_STALL: - * case USBH_URBSTATUS_DISCONNECTED: - * case USBH_URBSTATUS_OK: */ - default: - /* already finished */ - _usbh_urb_completeI(urb, status); - return TRUE; - - case USBH_URBSTATUS_PENDING: + if (urb->status == USBH_URBSTATUS_PENDING) { return usbh_lld_urb_abort(urb, status); } + + /* already finished or never submitted: + * USBH_URBSTATUS_INITIALIZED, USBH_URBSTATUS_ERROR, USBH_URBSTATUS_TIMEOUT, + * USBH_URBSTATUS_CANCELLED, USBH_URBSTATUS_STALL, USBH_URBSTATUS_DISCONNECTED + * USBH_URBSTATUS_OK */ + return TRUE; } void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status) { @@ -430,7 +423,7 @@ usbh_urbstatus_t usbhControlRequest(usbh_device_t *dev, wIndex, wLength }; - return usbhControlRequestExtended(dev, &req, buff, NULL, TIME_INFINITE); + return usbhControlRequestExtended(dev, &req, buff, NULL, HAL_USBH_CONTROL_REQUEST_DEFAULT_TIMEOUT); } /*===========================================================================*/ @@ -896,46 +889,48 @@ static void _port_process_status_change(usbh_port_t *port) { _port_update_status(port); if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) { - /* port connected status changed */ port->c_status &= ~USBH_PORTSTATUS_C_CONNECTION; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_CONNECTION); - if ((port->status & (USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE)) - == USBH_PORTSTATUS_CONNECTION) { - if (port->device.status != USBH_DEVSTATUS_DISCONNECTED) { + + if (port->device.status != USBH_DEVSTATUS_DISCONNECTED) { + if (!(port->status & USBH_PORTSTATUS_CONNECTION)) { _usbh_port_disconnected(port); } + } + } - /* connected, disabled */ + if (port->device.status == USBH_DEVSTATUS_DISCONNECTED) { + if (port->status & USBH_PORTSTATUS_CONNECTION) { _port_connected(port); - } else { - /* disconnected */ - _usbh_port_disconnected(port); } } if (port->c_status & USBH_PORTSTATUS_C_RESET) { port->c_status &= ~USBH_PORTSTATUS_C_RESET; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_RESET); + uinfof("Port %d: reset=%d", port->number, port->status & USBH_PORTSTATUS_RESET ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_ENABLE) { port->c_status &= ~USBH_PORTSTATUS_C_ENABLE; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_ENABLE); + uinfof("Port %d: enable=%d", port->number, port->status & USBH_PORTSTATUS_ENABLE ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_OVERCURRENT) { port->c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_OVERCURRENT); + uwarnf("Port %d: overcurrent=%d", port->number, port->status & USBH_PORTSTATUS_OVERCURRENT ? 1 : 0); } if (port->c_status & USBH_PORTSTATUS_C_SUSPEND) { port->c_status &= ~USBH_PORTSTATUS_C_SUSPEND; usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_SUSPEND); + uinfof("Port %d: suspend=%d", port->number, port->status & USBH_PORTSTATUS_SUSPEND ? 1 : 0); } } - static void _port_connected(usbh_port_t *port) { /* connected */ @@ -945,9 +940,8 @@ static void _port_connected(usbh_port_t *port) { usbh_devspeed_t speed; USBH_DEFINE_BUFFER(usbh_string_descriptor_t strdesc); - uinfof("Port %d connected, wait debounce...", port->number); - port->device.status = USBH_DEVSTATUS_ATTACHED; + uinfof("Port %d: attached, wait debounce...", port->number); /* wait for attach de-bounce */ osalThreadSleepMilliseconds(HAL_USBH_PORT_DEBOUNCE_TIME); @@ -955,16 +949,26 @@ static void _port_connected(usbh_port_t *port) { /* check disconnection */ _port_update_status(port); if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) { - /* connection state changed; abort */ + port->c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_CONNECTION); + uwarnf("Port %d: connection state changed; abort #1", port->number); + goto abort; + } + + /* make sure that the device is still connected */ + if ((port->status & USBH_PORTSTATUS_CONNECTION) == 0) { + uwarnf("Port %d: device is disconnected", port->number); goto abort; } + uinfof("Port %d: connected", port->number); port->device.status = USBH_DEVSTATUS_CONNECTED; retries = 3; reset: for (i = 0; i < 3; i++) { - uinfo("Try reset..."); + uinfof("Port %d: Try reset...", port->number); + /* TODO: check that port is actually disabled */ port->c_status &= ~(USBH_PORTSTATUS_C_RESET | USBH_PORTSTATUS_C_ENABLE); _port_reset(port); osalThreadSleepMilliseconds(20); /* give it some time to reset (min. 10ms) */ @@ -973,8 +977,12 @@ reset: _port_update_status(port); /* check for disconnection */ - if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) + if (port->c_status & USBH_PORTSTATUS_C_CONNECTION) { + port->c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + usbhhubClearFeaturePort(port, USBH_PORT_FEAT_C_CONNECTION); + uwarnf("Port %d: connection state changed; abort #2", port->number); goto abort; + } /* check for reset completion */ if (port->c_status & USBH_PORTSTATUS_C_RESET) { @@ -988,7 +996,10 @@ reset: } /* check for timeout */ - if (osalOsGetSystemTimeX() - start > HAL_USBH_PORT_RESET_TIMEOUT) break; + if (osalOsGetSystemTimeX() - start > HAL_USBH_PORT_RESET_TIMEOUT) { + uwarnf("Port %d: reset timeout", port->number); + break; + } } } @@ -996,8 +1007,7 @@ reset: goto abort; reset_success: - - uinfo("Reset OK, recovery..."); + uinfof("Port %d: Reset OK, recovery...", port->number); /* reset recovery */ osalThreadSleepMilliseconds(100); @@ -1014,19 +1024,22 @@ reset_success: usbhEPOpen(&port->device.ctrl); /* device with default address (0), try enumeration */ - if (_device_enumerate(&port->device)) { + if (_device_enumerate(&port->device) != HAL_SUCCESS) { /* enumeration failed */ usbhEPClose(&port->device.ctrl); - if (!--retries) + if (!--retries) { + uwarnf("Port %d: enumeration failed; abort", port->number); goto abort; + } /* retry reset & enumeration */ + uwarnf("Port %d: enumeration failed; retry reset & enumeration", port->number); goto reset; } /* load the default language ID */ - uinfo("Loading langID0..."); + uinfof("Port %d: Loading langID0...", port->number); if (!usbhStdReqGetStringDescriptor(&port->device, 0, 0, USBH_DT_STRING_SIZE, (uint8_t *)&strdesc) && (strdesc.bLength >= 4) @@ -1034,12 +1047,12 @@ reset_success: 4, (uint8_t *)&strdesc)) { port->device.langID0 = strdesc.wData[0]; - uinfof("langID0=%04x", port->device.langID0); + uinfof("Port %d: langID0=%04x", port->number, port->device.langID0); } /* check if the device has only one configuration */ if (port->device.devDesc.bNumConfigurations == 1) { - uinfo("Device has only one configuration"); + uinfof("Port %d: device has only one configuration", port->number); _device_configure(&port->device, 0); } @@ -1047,7 +1060,7 @@ reset_success: return; abort: - uerr("Abort"); + uerrf("Port %d: abort", port->number); port->device.status = USBH_DEVSTATUS_DISCONNECTED; } @@ -1055,14 +1068,14 @@ void _usbh_port_disconnected(usbh_port_t *port) { if (port->device.status == USBH_DEVSTATUS_DISCONNECTED) return; - uinfo("Port disconnected"); + uinfof("Port %d: disconnected", port->number); /* unload drivers */ while (port->device.drivers) { usbh_baseclassdriver_t *drv = port->device.drivers; /* unload */ - uinfof("Unload driver %s", drv->info->name); + uinfof("Port %d: unload driver %s", port->number, drv->info->name); drv->info->vmt->unload(drv); /* unlink */ @@ -1071,9 +1084,7 @@ void _usbh_port_disconnected(usbh_port_t *port) { } /* close control endpoint */ - osalSysLock(); - usbhEPCloseS(&port->device.ctrl); - osalSysUnlock(); + usbhEPClose(&port->device.ctrl); /* free address */ if (port->device.address) @@ -1113,7 +1124,7 @@ static void _hub_process_status_change(USBHDriver *host, USBHHubDriver *hub) { uinfo("Hub status change. GET_STATUS."); _hub_update_status(host, hub); - if (hub->c_status & USBH_HUBSTATUS_C_HUB_LOCAL_POWER) { + if (hub->c_status & USBH_HUBSTATUS_C_HUB_LOCAL_POWER) { hub->c_status &= ~USBH_HUBSTATUS_C_HUB_LOCAL_POWER; uinfo("Clear USBH_HUB_FEAT_C_HUB_LOCAL_POWER"); usbhhubClearFeatureHub(host, hub, USBH_HUB_FEAT_C_HUB_LOCAL_POWER); @@ -1196,8 +1207,8 @@ void usbhMainLoop(USBHDriver *usbh) { _hub_process(usbh, NULL); /* process connected hubs */ - USBHHubDriver *hub; - list_for_each_entry(hub, USBHHubDriver, &usbh->hubs, node) { + USBHHubDriver *hub, *temp; + list_for_each_entry_safe(hub, USBHHubDriver, temp, &usbh->hubs, node) { _hub_process(usbh, hub); } #else -- cgit v1.2.3 From ca1882c01b7055a9dd16468e093e11ae87c65757 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 31 Jul 2017 18:46:22 -0300 Subject: USBH: improved debug output --- os/hal/include/hal_usbh.h | 8 +---- os/hal/src/usbh/TODO.txt | 2 +- os/hal/src/usbh/hal_usbh_debug.c | 72 ++++++++++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 26 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/hal_usbh.h b/os/hal/include/hal_usbh.h index 3e69607..1ed6416 100644 --- a/os/hal/include/hal_usbh.h +++ b/os/hal/include/hal_usbh.h @@ -60,13 +60,6 @@ #include "usbh/list.h" #include "usbh/defs.h" -/* TODO: - * - * - Integrate VBUS power switching functionality to the API. - * - */ - - /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ @@ -83,6 +76,7 @@ enum usbh_status { USBH_STATUS_SUSPENDED, }; +/* These correspond to the USB spec */ enum usbh_devstatus { USBH_DEVSTATUS_DISCONNECTED = 0, USBH_DEVSTATUS_ATTACHED, diff --git a/os/hal/src/usbh/TODO.txt b/os/hal/src/usbh/TODO.txt index 532420b..87269be 100644 --- a/os/hal/src/usbh/TODO.txt +++ b/os/hal/src/usbh/TODO.txt @@ -18,4 +18,4 @@ Enhancements: - A way to automate matching (similar to linux) - Hooks to override driver loading and to inform the user of problems - for STM32 LLD: think of a way to prevent Bulk IN NAK interrupt flood. - +- Integrate VBUS power switching functionality to the API. diff --git a/os/hal/src/usbh/hal_usbh_debug.c b/os/hal/src/usbh/hal_usbh_debug.c index df773e1..d32f1c6 100644 --- a/os/hal/src/usbh/hal_usbh_debug.c +++ b/os/hal/src/usbh/hal_usbh_debug.c @@ -342,19 +342,39 @@ unsigned_common: } -static void _print_hdr(void) -{ +static systime_t first, last; +static bool ena; +static uint32_t hdr[2]; + +static void _build_hdr(void) { uint32_t hfnum = USBH_DEBUG_USBHD.otg->HFNUM; uint16_t hfir = USBH_DEBUG_USBHD.otg->HFIR; + last = osalOsGetSystemTimeX(); + if (ena) { + first = last; + } - _put(0xff); - _put(0xff); - _put(hfir & 0xff); - _put(hfir >> 8); - _put(hfnum & 0xff); - _put((hfnum >> 8) & 0xff); - _put((hfnum >> 16) & 0xff); - _put((hfnum >> 24) & 0xff); + if (((hfnum & 0x3fff) == 0x3fff) && (hfir == (hfnum >> 16))) { + hdr[0] = 0xfeff; + hdr[1] = last - first; + ena = FALSE; + } else { + hdr[0] = 0xffff | (hfir << 16); + hdr[1] = hfnum; + ena = TRUE; + } +} + +static void _print_hdr(void) +{ + _put(hdr[0] & 0xff); + _put((hdr[0] >> 8) & 0xff); + _put((hdr[0] >> 16) & 0xff); + _put((hdr[0] >> 24) & 0xff); + _put(hdr[1] & 0xff); + _put((hdr[1] >> 8) & 0xff); + _put((hdr[1] >> 16) & 0xff); + _put((hdr[1] >> 24) & 0xff); } void usbDbgPrintf(const char *fmt, ...) @@ -365,6 +385,7 @@ void usbDbgPrintf(const char *fmt, ...) input_queue_t *iqp = &USBH_DEBUG_USBHD.iq; int rem = sizeof(USBH_DEBUG_USBHD.dbg_buff) - iqp->q_counter; if (rem >= 9) { + _build_hdr(); _print_hdr(); _dbg_printf(fmt, ap); iqp->q_counter++; @@ -378,11 +399,8 @@ void usbDbgPrintf(const char *fmt, ...) void usbDbgPuts(const char *s) { - uint32_t buff[2] = { - 0xffff | (USBH_DEBUG_USBHD.otg->HFIR << 16), - USBH_DEBUG_USBHD.otg->HFNUM - }; - uint8_t *p = (uint8_t *)buff; + _build_hdr(); + uint8_t *p = (uint8_t *)hdr; uint8_t *top = p + 8; syssts_t sts = chSysGetStatusAndLockX(); @@ -488,8 +506,9 @@ static void usb_debug_thread(void *arg) { if (c == 0xff) state = 1; } else if (state == 1) { if (c == 0xff) state = 2; + else if (c == 0xfe) state = 3; else (state = 0); - } else { + } else if (state == 2) { uint16_t hfir; uint32_t hfnum; @@ -508,10 +527,26 @@ static void usb_debug_thread(void *arg) { uint32_t f = hfnum & 0xffff; uint32_t p = 1000 - ((hfnum >> 16) / (hfir / 1000)); - chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "%05d.%03d ", f, p); + chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "%05d.%03d ", f, p); + state = 4; + } else if (state == 3) { + uint32_t t; + c = iqGet(&host->iq); if (c < 0) goto reset; + c = iqGet(&host->iq); if (c < 0) goto reset; + + t = c; + c = iqGet(&host->iq); if (c < 0) goto reset; + t |= c << 8; + c = iqGet(&host->iq); if (c < 0) goto reset; + t |= c << 16; + c = iqGet(&host->iq); if (c < 0) goto reset; + t |= c << 24; + + chprintf((BaseSequentialStream *)&USBH_DEBUG_SD, "+%08d ", t); + state = 4; + } else { while (true) { - c = iqGet(&host->iq); if (c < 0) goto reset; if (!c) { sdPut(&USBH_DEBUG_SD, '\r'); sdPut(&USBH_DEBUG_SD, '\n'); @@ -519,6 +554,7 @@ static void usb_debug_thread(void *arg) { break; } sdPut(&USBH_DEBUG_SD, (uint8_t)c); + c = iqGet(&host->iq); if (c < 0) goto reset; } } -- cgit v1.2.3 From 02585210d1f33b3d5dd52267faa15576d5f7f8b2 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Mon, 31 Jul 2017 18:48:23 -0300 Subject: USBH: STM32 LLD: various improvements - general cleanup - implemented workaround to undocumented erratum (the OTG core may report successful enabling of port when connecting a low-speed device, but really it generates no traffic and remains in a "dumb" state) - improved handling of disconnection of devices (avoid submitting URBs if the port is disabled) --- os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 244 +++++++++++++++------------ os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h | 2 + 2 files changed, 134 insertions(+), 112 deletions(-) (limited to 'os/hal') diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index 3a581f5..3944a79 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -127,16 +127,6 @@ static inline void _save_dt_mask(usbh_ep_t *ep, uint32_t hctsiz) { ep->dt_mask = hctsiz & HCTSIZ_DPID_MASK; } -#if 1 -#define _transfer_completed _transfer_completedI -#else -static inline void _transfer_completed(usbh_ep_t *ep, usbh_urb_t *urb, usbh_urbstatus_t status) { - osalSysLockFromISR(); - _transfer_completedI(ep, urb, status); - osalSysUnlockFromISR(); -} -#endif - /*===========================================================================*/ /* Functions called from many places. */ /*===========================================================================*/ @@ -466,7 +456,7 @@ static void _purge_queue(USBHDriver *host, struct list_head *list) { _release_channel(host, hcm); _update_urb(ep, hcm->hc->HCTSIZ, urb, FALSE); } - _transfer_completed(ep, urb, USBH_URBSTATUS_DISCONNECTED); + _transfer_completedI(ep, urb, USBH_URBSTATUS_DISCONNECTED); } } @@ -622,6 +612,13 @@ bool usbh_lld_ep_reset(usbh_ep_t *ep) { void usbh_lld_urb_submit(usbh_urb_t *urb) { usbh_ep_t *const ep = urb->ep; + USBHDriver *const host = ep->device->host; + + if (!(host->otg->HPRT & HPRT_PENA)) { + uwarnf("\t%s: Can't submit URB, port disabled", ep->name); + _usbh_urb_completeI(urb, USBH_URBSTATUS_DISCONNECTED); + return; + } /* add the URB to the EP's queue */ list_add_tail(&urb->node, &ep->urb_list); @@ -633,7 +630,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) { _move_to_pending_queue(ep); if (usbhEPIsPeriodic(ep)) { - ep->device->host->otg->GINTMSK |= GINTMSK_SOFM; + host->otg->GINTMSK |= GINTMSK_SOFM; } else { /* try to queue non-periodic transfers */ _try_commit_np(ep->device->host); @@ -666,7 +663,7 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { return FALSE; } - /* This URB is active, we can cancel it now */ + /* This URB is inactive, we can cancel it now */ uinfof("\t%s: usbh_lld_urb_abort: URB is not active", ep->name); _transfer_completedI(ep, urb, status); @@ -766,7 +763,7 @@ static void _complete_bulk_int(USBHDriver *host, stm32_hc_management_t *hcm, usb _save_dt_mask(ep, hctsiz); if (_update_urb(ep, hctsiz, urb, TRUE)) { udbgf("\t%s: done", ep->name); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } else { osalDbgCheck(urb->requestedLength > 0x7FFFF); uwarnf("\t%s: incomplete", ep->name); @@ -797,7 +794,7 @@ static void _complete_control(USBHDriver *host, stm32_hc_management_t *hcm, usbh } else { osalDbgCheck(ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_STATUS); udbgf("\t%s: STATUS done", ep->name); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } _try_commit_np(host); } @@ -823,7 +820,7 @@ static void _complete_iso(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_ udbgf("\t%s: done", hcm->ep->name); _release_channel(host, hcm); _update_urb(ep, hctsiz, urb, TRUE); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); _try_commit_p(host, FALSE); } @@ -908,7 +905,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ switch (reason) { case USBH_LLD_HALTREASON_NAK: if ((ep->type == USBH_EPTYPE_INT) && ep->in) { - _transfer_completed(ep, urb, USBH_URBSTATUS_TIMEOUT); + _transfer_completedI(ep, urb, USBH_URBSTATUS_TIMEOUT); } else { ep->xfer.error_count = 0; _move_to_pending_queue(ep); @@ -923,12 +920,12 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ } else { ep->status = USBH_EPSTATUS_HALTED; } - _transfer_completed(ep, urb, USBH_URBSTATUS_STALL); + _transfer_completedI(ep, urb, USBH_URBSTATUS_STALL); break; case USBH_LLD_HALTREASON_ERROR: if ((ep->type == USBH_EPTYPE_ISO) || done || (ep->xfer.error_count >= 3)) { - _transfer_completed(ep, urb, USBH_URBSTATUS_ERROR); + _transfer_completedI(ep, urb, USBH_URBSTATUS_ERROR); } else { uerrf("\t%s: err=%d, done=%d, retry", ep->name, ep->xfer.error_count, done); _move_to_pending_queue(ep); @@ -937,7 +934,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ case USBH_LLD_HALTREASON_ABORT: uwarnf("\t%s: Abort", ep->name); - _transfer_completed(ep, urb, urb->status); + _transfer_completedI(ep, urb, urb->status); break; default: @@ -1024,6 +1021,36 @@ static inline void _hcint_int(USBHDriver *host) { /* Host interrupts. */ /*===========================================================================*/ static inline void _sof_int(USBHDriver *host) { + + /* this is part of the workaround to the LS bug in the OTG core */ +#undef HPRT_PLSTS_MASK +#define HPRT_PLSTS_MASK (3U<<10) + if (host->check_ls_activity) { + uint16_t remaining = host->otg->HFNUM >> 16; + if (remaining < 5975) { + uwarnf("LS: ISR called too late (time=%d)", 6000 - remaining); + return; + } + /* 15us loop */ + for (;;) { + uint32_t line_status = host->otg->HPRT & HPRT_PLSTS_MASK; + remaining = host->otg->HFNUM >> 16; + if (line_status != HPRT_PLSTS_DM) { + uinfof("LS: activity detected, line=%d, time=%d", line_status >> 10, 6000 - remaining); + host->check_ls_activity = FALSE; + host->otg->GINTMSK = (host->otg->GINTMSK & ~GINTMSK_SOFM) | (GINTMSK_HCM | GINTMSK_RXFLVLM); + host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; + return; + } + if (remaining < 5910) { + uwarn("LS: No activity detected"); + return; + } + } + } + + /* real SOF interrupt */ udbg("SOF"); _try_commit_p(host, TRUE); } @@ -1143,17 +1170,19 @@ static inline void _ptxfe_int(USBHDriver *host) { uinfo("PTXFE"); } -static inline void _discint_int(USBHDriver *host) { - uint32_t hprt = host->otg->HPRT; - - uwarn("\tDISCINT"); +static void _disable(USBHDriver *host) { + host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE); + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE; - if (!(hprt & HPRT_PCSTS)) { - host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE); - host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE; - } _purge_active(host); _purge_pending(host); + + host->otg->GINTMSK &= ~(GINTMSK_HCM | GINTMSK_RXFLVLM); +} + +static inline void _discint_int(USBHDriver *host) { + uinfo("DISCINT: Port disconnection detected"); + _disable(host); } static inline void _hprtint_int(USBHDriver *host) { @@ -1169,8 +1198,6 @@ static inline void _hprtint_int(USBHDriver *host) { uinfo("\tHPRT: Port connection detected"); host->rootport.lld_status |= USBH_PORTSTATUS_CONNECTION; host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION; - } else { - uinfo("\tHPRT: Port disconnection detected"); } } @@ -1178,9 +1205,32 @@ static inline void _hprtint_int(USBHDriver *host) { hprt_clr |= HPRT_PENCHNG; if (hprt & HPRT_PENA) { uinfo("\tHPRT: Port enabled"); - host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; host->rootport.lld_status &= ~(USBH_PORTSTATUS_HIGH_SPEED | USBH_PORTSTATUS_LOW_SPEED); + /* configure FIFOs */ +#define HNPTXFSIZ DIEPTXF0 +#if STM32_USBH_USE_OTG1 +#if STM32_USBH_USE_OTG2 + if (&USBHD1 == host) +#endif + { + otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4); + otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG1_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4); + otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4); + } +#endif +#if STM32_USBH_USE_OTG2 +#if STM32_USBH_USE_OTG1 + if (&USBHD2 == host) +#endif + { + otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4); + otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG2_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4); + otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4); + } +#endif +#undef HNPTXFSIZ + /* Make sure the FIFOs are flushed. */ otg_txfifo_flush(host, 0x10); otg_rxfifo_flush(host); @@ -1197,9 +1247,23 @@ static inline void _hprtint_int(USBHDriver *host) { host->rootport.lld_status |= USBH_PORTSTATUS_LOW_SPEED; otg->HFIR = 6000; otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_6; + + /* Low speed devices connected to the STM32's internal transceiver sometimes + * don't behave correctly. Although HPRT reports a port enable, really + * no traffic is generated, and the core is non-functional. To avoid + * this we won't report the port enable until we are sure that the + * port is working. */ + host->check_ls_activity = TRUE; + otg->GINTMSK |= GINTMSK_SOFM; } else { otg->HFIR = 48000; otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_48; + host->check_ls_activity = FALSE; + + /* enable channel and rx interrupts */ + otg->GINTMSK |= GINTMSK_HCM | GINTMSK_RXFLVLM; + host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; } } else { if (hprt & HPRT_PCSTS) { @@ -1211,13 +1275,8 @@ static inline void _hprtint_int(USBHDriver *host) { } else { uerr("\tHPRT: Port disabled due to disconnect"); } - - _purge_active(host); - _purge_pending(host); - - host->rootport.lld_status &= ~USBH_PORTSTATUS_ENABLE; + _disable(host); } - host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; } if (hprt & HPRT_POCCHNG) { @@ -1249,24 +1308,19 @@ static void usb_lld_serve_interrupt(USBHDriver *host) { } /* check mismatch */ - if (gintsts & GINTSTS_MMIS) { - uerr("Mode Mismatch"); - otg->GINTSTS = gintsts; - return; - } + osalDbgAssert((gintsts & GINTSTS_MMIS) == 0, "mode mismatch"); gintsts &= otg->GINTMSK; -#if USBH_DEBUG_ENABLE_WARNINGS if (!gintsts) { +#if USBH_DEBUG_ENABLE_WARNINGS uint32_t a, b; a = otg->GINTSTS; b = otg->GINTMSK; - uwarnf("GINTSTS=%08x, GINTMSK=%08x", a, b); + uwarnf("Masked bits caused an ISR: GINTSTS=%08x, GINTMSK=%08x (unhandled bits=%08x)", a, b, a & ~b); +#endif return; } -#endif - // otg->GINTMSK &= ~(GINTMSK_NPTXFEM | GINTMSK_PTXFEM); otg->GINTSTS = gintsts; if (gintsts & GINTSTS_SOF) @@ -1365,24 +1419,22 @@ static void _init(USBHDriver *host) { #if STM32_USBH_USE_OTG1 #if STM32_USBH_USE_OTG2 - if (&USBHD1 == host) { + if (&USBHD1 == host) #endif + { host->otg = OTG_FS; host->channels_number = STM32_OTG1_CHANNELS_NUMBER; -#if STM32_USBH_USE_OTG2 } #endif -#endif #if STM32_USBH_USE_OTG2 #if STM32_USBH_USE_OTG1 - if (&USBHD2 == host) { + if (&USBHD2 == host) #endif + { host->otg = OTG_HS; host->channels_number = STM32_OTG2_CHANNELS_NUMBER; -#if STM32_USBH_USE_OTG1 } -#endif #endif INIT_LIST_HEAD(&host->ch_free[0]); INIT_LIST_HEAD(&host->ch_free[1]); @@ -1417,8 +1469,9 @@ static void _usbh_start(USBHDriver *usbh) { /* Clock activation.*/ #if STM32_USBH_USE_OTG1 #if STM32_USBH_USE_OTG2 - if (&USBHD1 == usbh) { + if (&USBHD1 == usbh) #endif + { /* OTG FS clock enable and reset.*/ rccEnableOTG_FS(FALSE); rccResetOTG_FS(); @@ -1427,15 +1480,14 @@ static void _usbh_start(USBHDriver *usbh) { /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY); -#if STM32_USBH_USE_OTG2 } #endif -#endif #if STM32_USBH_USE_OTG2 #if STM32_USBH_USE_OTG1 - if (&USBHD2 == usbh) { + if (&USBHD2 == usbh) #endif + { /* OTG HS clock enable and reset.*/ rccEnableOTG_HS(TRUE); // Enable HS clock when cpu is in sleep mode rccDisableOTG_HSULPI(TRUE); // Disable HS ULPI clock when cpu is in sleep mode @@ -1445,9 +1497,7 @@ static void _usbh_start(USBHDriver *usbh) { /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY); -#if STM32_USBH_USE_OTG1 } -#endif #endif otgp->GUSBCFG = GUSBCFG_PHYSEL | GUSBCFG_TRDT(5); @@ -1487,41 +1537,11 @@ static void _usbh_start(USBHDriver *usbh) { otgp->HPRT |= HPRT_PPWR; - /* without this delay, the FIFO sizes are set INcorrectly */ - osalThreadSleepS(MS2ST(200)); - -#define HNPTXFSIZ DIEPTXF0 -#if STM32_USBH_USE_OTG1 -#if STM32_USBH_USE_OTG2 - if (&USBHD1 == usbh) { -#endif - otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4); - otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4); - otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4); -#if STM32_USBH_USE_OTG2 - } -#endif -#endif -#if STM32_USBH_USE_OTG2 -#if STM32_USBH_USE_OTG1 - if (&USBHD2 == usbh) { -#endif - otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4); - otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4); - otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4); -#if STM32_USBH_USE_OTG1 - } -#endif -#endif -#undef HNPTXFSIZ - otg_txfifo_flush(usbh, 0x10); otg_rxfifo_flush(usbh); otgp->GINTSTS = 0xffffffff; - otgp->GINTMSK = GINTMSK_DISCM /*| GINTMSK_PTXFEM*/ | GINTMSK_HCM | GINTMSK_HPRTM - /*| GINTMSK_IPXFRM | GINTMSK_NPTXFEM*/ | GINTMSK_RXFLVLM - /*| GINTMSK_SOFM */ | GINTMSK_MMISM; + otgp->GINTMSK = GINTMSK_DISCM | GINTMSK_HPRTM | GINTMSK_MMISM; usbh->rootport.lld_status = USBH_PORTSTATUS_POWER; usbh->rootport.lld_c_status = 0; @@ -1586,7 +1606,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case USBH_PORT_FEAT_C_OVERCURRENT: - usbh->rootport.lld_c_status &= USBH_PORTSTATUS_C_OVERCURRENT; + usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; break; default: @@ -1597,18 +1617,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case GetHubDescriptor: - /*dev_dbg(hsotg->dev, "GetHubDescriptor\n"); - hub_desc = (struct usb_hub_descriptor *)buf; - hub_desc->bDescLength = 9; - hub_desc->bDescriptorType = USB_DT_HUB; - hub_desc->bNbrPorts = 1; - hub_desc->wHubCharacteristics = - cpu_to_le16(HUB_CHAR_COMMON_LPSM | - HUB_CHAR_INDV_PORT_OCPM); - hub_desc->bPwrOn2PwrGood = 1; - hub_desc->bHubContrCurrent = 0; - hub_desc->u.hs.DeviceRemovable[0] = 0; - hub_desc->u.hs.DeviceRemovable[1] = 0xff;*/ + osalDbgAssert(0, "unsupported"); break; case GetHubStatus: @@ -1644,11 +1653,29 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy uint32_t hprt; otg->PCGCCTL = 0; hprt = otg->HPRT; + if (hprt & HPRT_PENA) { + /* This can occur when the OTG core doesn't generate traffic + * despite reporting a successful por enable */ + uerr("Detected enabled port; resetting OTG core"); + otg->GAHBCFG = 0; + osalThreadSleepS(MS2ST(20)); + _usbh_start(usbh); /* this effectively resets the core */ + osalThreadSleepS(MS2ST(100)); /* during this delay, the core generates connect ISR */ + uinfo("OTG reset ended"); + if (otg->HPRT & HPRT_PCSTS) { + /* if the device is still connected, don't report a C_CONNECTION flag, which would cause + * the upper layer to abort enumeration */ + uinfo("Clear connection change flag"); + usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + } + } /* note: writing PENA = 1 actually disables the port */ - hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG ); + hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG); + while ((otg->GRSTCTL & GRSTCTL_AHBIDL) == 0); otg->HPRT = hprt | HPRT_PRST; - osalThreadSleepS(MS2ST(60)); + osalThreadSleepS(MS2ST(15)); otg->HPRT = hprt; + osalThreadSleepS(MS2ST(10)); usbh->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET; osalSysUnlock(); } break; @@ -1672,14 +1699,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy } uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh) { - osalSysLock(); - if (usbh->rootport.lld_c_status) { - osalSysUnlock(); - return 1 << 1; - } - osalSysUnlock(); - return 0; + return usbh->rootport.lld_c_status ? (1 << 1) : 0; } - #endif diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h index a2b7628..fd7f4e0 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h @@ -63,6 +63,8 @@ typedef struct stm32_hc_management { #define _usbhdriver_ll_data \ stm32_otg_t *otg; \ + /* low-speed port reset bug */ \ + bool check_ls_activity; \ /* channels */ \ uint8_t channels_number; \ stm32_hc_management_t channels[STM32_OTG2_CHANNELS_NUMBER]; \ -- cgit v1.2.3