a
Dependencies: FATFileSystem mbed-rtos
Fork of USBHost by
Revision 37:f1e388e7b752, committed 2017-07-20
- Comitter:
- Kojto
- Date:
- Thu Jul 20 10:13:56 2017 +0100
- Parent:
- 36:655a8c5fa238
- Child:
- 38:d66f404b66d4
- Commit message:
- Update libraries (ed9d1da)
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F401xE/TARGET_NUCLEO_F401RE/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,20 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#define USBHALHOST_64pins +#include "USBHALHost_STM_144_64pins.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F411xE/TARGET_NUCLEO_F411RE/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,40 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* 144 pins boards */ +#if defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_F446ZE) || defined(TARGET_NUCLEO_F207ZG) \ +|| defined(TARGET_NUCLEO_F767ZI) || defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_F412ZG) \ +|| defined(TARGET_DISCO_F413ZH) +#include "USBHALHost_STM_144_64pins.h" +#endif + +/* 64 pins boards */ +#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_L476RG) || defined(TARGET_NUCLEO_F411RE) +#define USBHALHOST_64pins +#include "USBHALHost_STM_144_64pins.h" +#endif + +/* DISCO board */ + +#ifdef TARGET_DISCO_F429ZI +#include "USBHALHost_DISCOF429ZI.h" +#endif + +#ifdef TARGET_DISCO_L476VG +#include "USBHALHost_DISCOL476VG.h" +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_DISCO_F429ZI/USBHALHost_DISCOF429ZI.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,112 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef USBHALHOST_DISCOF429ZI +#define USBHALHOST_DISCOF429ZI + +#define USBHAL_IRQn OTG_HS_IRQn + +#define HCCA_SIZE sizeof(HCD_HandleTypeDef) +#define ED_SIZE sizeof(HCED) +#define TD_SIZE sizeof(HCTD) + +#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) +/* STM device FS have 11 channels (definition is for 60 channels) */ +static volatile uint8_t usb_buf[TOTAL_SIZE]; +typedef struct +{ + /* store the request ongoing on each endpoit */ + /* 1st field of structure avoid giving knowledge of all structure to + * endpoint */ + volatile uint32_t addr[MAX_ENDPOINT]; + USBHALHost *inst; + void (USBHALHost::*deviceConnected)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent); + void (USBHALHost::*deviceDisconnected)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr); + void (USBHALHost::*transferCompleted)(volatile uint32_t addr); +}USBHALHost_Private_t; +/* CONFIGURATION for USB_VBUS + * on 64 bits board PC_0 is used (0 VBUS on, 1 VBUS off) + * on 144 pins board PG_6 is used ( 1 VBUS on, 0 VBUS on) + */ +static gpio_t gpio_vbus; + +#define VBUS_OFF 1 +#define VBUS_ON 0 +#define USB_VBUS_CONFIG \ + do {__HAL_RCC_GPIOC_CLK_ENABLE();\ + gpio_init_out_ex(&gpio_vbus, PC_4, VBUS_OFF);\ + }while(0); + + +void usb_vbus( uint8_t state) +{ + if(state == 0) + { + gpio_write(&gpio_vbus, VBUS_OFF); + } + else + { + gpio_write(&gpio_vbus, VBUS_ON); + } + wait(0.2); +} + + +USBHALHost::USBHALHost() { + gpio_t pin_vbus; + instHost = this; + HCD_HandleTypeDef *hhcd; + USBHALHost_Private_t *HALPriv = new(USBHALHost_Private_t); + memset(HALPriv, 0, sizeof(USBHALHost_Private_t)); + memInit(); + memset((void*)usb_hcca, 0, HCCA_SIZE); + hhcd = (HCD_HandleTypeDef *)usb_hcca; + hhcd->Instance = USB_OTG_HS; + hhcd->pData = (void*)HALPriv; + hhcd->Init.Host_channels = 11; + /* for now failed with dma */ + hhcd->Init.dma_enable = 0; + hhcd->Init.speed = HCD_SPEED_HIGH; + hhcd->Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd->Init.use_external_vbus = 1; + HALPriv->inst = this; + HALPriv->deviceConnected = &USBHALHost::deviceConnected; + HALPriv->deviceDisconnected = &USBHALHost::deviceDisconnected; + HALPriv->transferCompleted = &USBHALHost::transferCompleted; + for (int i = 0; i < MAX_ENDPOINT; i++) { + edBufAlloc[i] = false; + HALPriv->addr[i]=(uint32_t)-1; + } + for (int i = 0; i < MAX_TD; i++) { + tdBufAlloc[i] = false; + } + /* Configure USB HS GPIOs */ + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*USB DM and DP */ + pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); + pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); + /* Configure VBUS Pin */ + gpio_init_in(&pin_vbus, PB_13); + /* Configure POWER_SWITCH IO pin */ + USB_VBUS_CONFIG; + /* Enable USB HS Clocks */ + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + + /* Set USBFS Interrupt priority */ + HAL_NVIC_SetPriority(USBHAL_IRQn, 5, 0); + NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_DISCO_F429ZI/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_DISCOF429ZI.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_NUCLEO_F429ZI/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_NUCLEO_F439ZI/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_STM_144_64pins.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/USBHALHost_DISCOL476VG.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,118 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef USBHALHOST_DISCOL476VG +#define USBHALHOST_DISCOL476VG + +#define USBHAL_IRQn OTG_FS_IRQn + +#define HCCA_SIZE sizeof(HCD_HandleTypeDef) +#define ED_SIZE sizeof(HCED) +#define TD_SIZE sizeof(HCTD) + +#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) +/* STM device FS have 11 channels (definition is for 60 channels) */ +static volatile uint8_t usb_buf[TOTAL_SIZE]; +typedef struct +{ + /* store the request ongoing on each endpoit */ + /* 1st field of structure avoid giving knowledge of all structure to + * endpoint */ + volatile uint32_t addr[MAX_ENDPOINT]; + USBHALHost *inst; + void (USBHALHost::*deviceConnected)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent); + void (USBHALHost::*deviceDisconnected)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr); + void (USBHALHost::*transferCompleted)(volatile uint32_t addr); +}USBHALHost_Private_t; + +static gpio_t gpio_vbus; + +#define VBUS_OFF 1 +#define VBUS_ON 0 +#define USB_VBUS_CONFIG \ + do {\ + gpio_init_out_ex(&gpio_vbus, PC_9, VBUS_OFF);\ + }while(0); + + +void usb_vbus( uint8_t state) +{ + if(state == 0) + { + gpio_write(&gpio_vbus, VBUS_OFF); + } + else + { + gpio_write(&gpio_vbus, VBUS_ON); + } + wait(0.2); +} + + +USBHALHost::USBHALHost() { + instHost = this; + HCD_HandleTypeDef *hhcd; + USBHALHost_Private_t *HALPriv = new(USBHALHost_Private_t); + memset(HALPriv, 0, sizeof(USBHALHost_Private_t)); + memInit(); + memset((void*)usb_hcca, 0, HCCA_SIZE); + hhcd = (HCD_HandleTypeDef *)usb_hcca; + hhcd->Instance = USB_OTG_FS; + hhcd->pData = (void*)HALPriv; + hhcd->Init.Host_channels = 11; + /* for now failed with dma */ + hhcd->Init.dma_enable = 0; + hhcd->Init.speed = HCD_SPEED_FULL; + hhcd->Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd->Init.use_external_vbus = 1; + HALPriv->inst = this; + HALPriv->deviceConnected = &USBHALHost::deviceConnected; + HALPriv->deviceDisconnected = &USBHALHost::deviceDisconnected; + HALPriv->transferCompleted = &USBHALHost::transferCompleted; + for (int i = 0; i < MAX_ENDPOINT; i++) { + edBufAlloc[i] = false; + HALPriv->addr[i]=(uint32_t)-1; + } + for (int i = 0; i < MAX_TD; i++) { + tdBufAlloc[i] = false; + } + __HAL_RCC_PWR_CLK_ENABLE(); +#ifdef TARGET_STM32L4 + HAL_PWREx_EnableVddUSB(); +#endif + + /* Configure USB HS GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /*USB DM and DP */ + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); + + /* Configure VBUS Pin */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); + /* Configure POWER_SWITCH IO pin */ + USB_VBUS_CONFIG; + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Enable USB FS Clocks */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + /* Set USBFS Interrupt priority */ + HAL_NVIC_SetPriority(USBHAL_IRQn, 5, 0); + NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,18 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#include "USBHALHost_DISCOL476VG.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#define USBHALHOST_64pins +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/USBHALHost_STM_TARGET.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,19 @@ +/* Copyright (c) 2016 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#define USBHALHOST_64pins +#include "USBHALHost_STM_144_64pins.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/USBEndpoint_STM.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,182 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if defined(TARGET_STM) && defined(USBHOST_OTHER) + +#include "dbg.h" +#include "USBEndpoint.h" +extern uint32_t HAL_HCD_HC_GetMaxPacket(HCD_HandleTypeDef *hhcd, uint8_t chn_num); +extern uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chn_num); +extern void HAL_HCD_DisableInt(HCD_HandleTypeDef* hhcd, uint8_t chn_num); +extern void HAL_HCD_EnableInt(HCD_HandleTypeDef* hhcd, uint8_t chn_num); + + + + +void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir_, uint32_t size, uint8_t ep_number, HCTD* td_list_[2]) +{ + HCD_HandleTypeDef *hhcd; + uint32_t *addr; + + hced = hced_; + type = type_; + dir = dir_; + setup = (type == CONTROL_ENDPOINT) ? true : false; + + //TDs have been allocated by the host + memcpy((HCTD**)td_list, td_list_, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define + memset(td_list_[0], 0, sizeof(HCTD)); + memset(td_list_[1], 0, sizeof(HCTD)); + + td_list[0]->ep = this; + td_list[1]->ep = this; + + address = (ep_number & 0x7F) | ((dir - 1) << 7); + this->size = size; + this->ep_number = ep_number; + transfer_len = 0; + transferred = 0; + buf_start = 0; + nextEp = NULL; + + td_current = td_list[0]; + td_next = td_list[1]; + /* remove potential post pending from previous endpoint */ + ep_queue.get(0); + intf_nb = 0; + hhcd = (HCD_HandleTypeDef*)hced->hhcd; + addr = &((uint32_t *)hhcd->pData)[hced->ch_num]; + *addr = 0; + state = USB_TYPE_IDLE; + speed =false; +} +void USBEndpoint::setSize(uint32_t size) +{ + this->size = size; +} + + +void USBEndpoint::setDeviceAddress(uint8_t addr) +{ + HCD_HandleTypeDef *hhcd; + uint8_t hcd_speed = HCD_SPEED_FULL; + /* fix me : small speed device with hub not supported + if (this->speed) hcd_speed = HCD_SPEED_LOW; */ + if (this->speed) { + USB_WARN("small speed device on hub not supported"); + } + MBED_ASSERT(HAL_HCD_HC_Init((HCD_HandleTypeDef*)hced->hhcd,hced->ch_num, address, addr, hcd_speed, type, size)!=HAL_BUSY); + this->device_address = addr; + +} + +void USBEndpoint::setSpeed(uint8_t speed) +{ + this->speed = speed; +} + + + +void USBEndpoint::setState(USB_TYPE st) +{ + /* modify this state is possible only with a plug */ + if (state == USB_TYPE_FREE) { + return; + } + + state = st; + if (st == USB_TYPE_FREE) { + HCD_HandleTypeDef *hhcd = (HCD_HandleTypeDef*)hced->hhcd; + uint32_t *addr = &((uint32_t *)hhcd->pData)[hced->ch_num]; + if ((*addr) && (type != INTERRUPT_ENDPOINT)) { + this->ep_queue.put((uint8_t*)1); + } + MBED_ASSERT(HAL_HCD_HC_Halt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num)!=HAL_BUSY); + HAL_HCD_DisableInt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num); + *addr = 0; + + } + if (st == USB_TYPE_ERROR) { + MBED_ASSERT(HAL_HCD_HC_Halt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num)!=HAL_BUSY); + HAL_HCD_DisableInt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num); + + } + if (st == USB_TYPE_ERROR) { + uint8_t hcd_speed = HCD_SPEED_FULL; + /* small speed device with hub not supported + if (this->speed) hcd_speed = HCD_SPEED_LOW;*/ + MBED_ASSERT(HAL_HCD_HC_Init((HCD_HandleTypeDef*)hced->hhcd,hced->ch_num, address, 0, hcd_speed, type, size)!=HAL_BUSY); + } +} + + +extern uint32_t HAL_HCD_HC_GetMaxPacket(HCD_HandleTypeDef *hhcd, uint8_t chn_num); +extern uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chn_num); + + +USB_TYPE USBEndpoint::queueTransfer() +{ + HCD_HandleTypeDef *hhcd = (HCD_HandleTypeDef*)hced->hhcd; + uint32_t *addr = &((uint32_t *)hhcd->pData)[hced->ch_num]; + uint32_t type = HAL_HCD_HC_GetType(hhcd, hced->ch_num); + uint32_t max_size = HAL_HCD_HC_GetMaxPacket(hhcd, hced->ch_num); + /* if a packet is queue on disconnected ; no solution for now */ + if (state == USB_TYPE_FREE) { + td_current->state = USB_TYPE_FREE; + return USB_TYPE_FREE; + } + ep_queue.get(0); + MBED_ASSERT(*addr ==0); + transfer_len = td_current->size <= max_size ? td_current->size : max_size; + buf_start = (uint8_t *)td_current->currBufPtr; + + //Now add this free TD at this end of the queue + state = USB_TYPE_PROCESSING; + /* one request */ + td_current->nextTD = (hcTd*)0; +#if defined(MAX_NYET_RETRY) + td_current->retry = 0; +#endif + td_current->setup = setup; + *addr = (uint32_t)td_current; + /* dir /setup is inverted for ST */ + /* token is useful only ctrl endpoint */ + /* last parameter is ping ? */ + MBED_ASSERT(HAL_HCD_HC_SubmitRequest((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num, dir-1, type,!setup,(uint8_t*) td_current->currBufPtr, transfer_len, 0)==HAL_OK); + HAL_HCD_EnableInt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num); + + return USB_TYPE_PROCESSING; +} + +void USBEndpoint::unqueueTransfer(volatile HCTD * td) +{ + if (state==USB_TYPE_FREE) { + return; + } + uint32_t *addr = &((uint32_t *)((HCD_HandleTypeDef*)hced->hhcd)->pData)[hced->ch_num]; + td->state=0; + td->currBufPtr=0; + td->size=0; + td->nextTD=0; + *addr = 0; + td_current = td_next; + td_next = td; +} + +void USBEndpoint::queueEndpoint(USBEndpoint * ed) +{ + nextEp = ed; +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/USBHALHost_STM.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,284 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef TARGET_STM +#include "mbed.h" +#include "USBHALHost.h" +#include "dbg.h" +#include "pinmap.h" + +#include "USBHALHost_STM_TARGET.h" + +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBHALHost_Private_t *priv=(USBHALHost_Private_t *)(hhcd->pData); + USBHALHost *obj= priv->inst; + void (USBHALHost::*func)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent ) = priv->deviceConnected; + (obj->*func)(0,1,0,NULL); +} +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USBHALHost_Private_t *priv=(USBHALHost_Private_t *)(hhcd->pData); + USBHALHost *obj= priv->inst; + void (USBHALHost::*func1)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr)= priv->deviceDisconnected; + (obj->*func1)(0,1,(USBHostHub *)NULL,0); +} +int HAL_HCD_HC_GetDirection(HCD_HandleTypeDef *hhcd,uint8_t chnum) +{ + /* useful for transmission */ + return hhcd->hc[chnum].ep_is_in; +} + +uint32_t HAL_HCD_HC_GetMaxPacket(HCD_HandleTypeDef *hhcd,uint8_t chnum) +{ + /* useful for transmission */ + return hhcd->hc[chnum].max_packet; +} + +void HAL_HCD_EnableInt(HCD_HandleTypeDef *hhcd,uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + USBx_HOST->HAINTMSK |= (1 << chnum); +} + + +void HAL_HCD_DisableInt(HCD_HandleTypeDef *hhcd,uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + USBx_HOST->HAINTMSK &= ~(1 << chnum); +} +uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd,uint8_t chnum) +{ + /* useful for transmission */ + return hhcd->hc[chnum].ep_type; +} + +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + USBHALHost_Private_t *priv=(USBHALHost_Private_t *)(hhcd->pData); + USBHALHost *obj= priv->inst; + void (USBHALHost::*func)(volatile uint32_t addr)= priv->transferCompleted; + + uint32_t addr = priv->addr[chnum]; + uint32_t max_size = HAL_HCD_HC_GetMaxPacket(hhcd, chnum); + uint32_t type = HAL_HCD_HC_GetType(hhcd, chnum); + uint32_t dir = HAL_HCD_HC_GetDirection(hhcd,chnum); + uint32_t length; + if ( (addr!=0)) { + HCTD *td = (HCTD *)addr; + + if ((type == EP_TYPE_BULK) || (type == EP_TYPE_CTRL )) { + switch (urb_state) { + case URB_DONE: +#if defined(MAX_NYET_RETRY) + td->retry = 0; +#endif + if (td->size > max_size) { + /* enqueue another request */ + td->currBufPtr += max_size; + td->size -= max_size; + length = td->size <= max_size ? td->size : max_size; + MBED_ASSERT(HAL_HCD_HC_SubmitRequest(hhcd, chnum, dir ,type , !td->setup,(uint8_t*) td->currBufPtr, length, 0)==HAL_OK); + HAL_HCD_EnableInt(hhcd, chnum); + return; + } + break; + case URB_NOTREADY: + /* try again */ + /* abritary limit , to avoid dead lock if other error than + * slow response is */ +#if defined(MAX_NYET_RETRY) + if (td->retry < MAX_NYET_RETRY) { + /* increment retry counter */ + td->retry++; +#endif + length = td->size <= max_size ? td->size : max_size; + MBED_ASSERT(HAL_HCD_HC_SubmitRequest(hhcd, chnum, dir ,type , !td->setup,(uint8_t*) td->currBufPtr, length, 0)==HAL_OK); + HAL_HCD_EnableInt(hhcd, chnum); + return; +#if defined(MAX_NYET_RETRY) + } else { + USB_ERR("urb_state != URB_NOTREADY"); + } +#endif + break; + } + } + if ((type == EP_TYPE_INTR) ) { + /* reply a packet of length NULL, this will be analyse in call back + * for mouse or hub */ + td->state =USB_TYPE_IDLE ; + HAL_HCD_DisableInt(hhcd, chnum); + + } else { + td->state = (urb_state == URB_DONE) ? USB_TYPE_IDLE : USB_TYPE_ERROR; + } + td->currBufPtr +=HAL_HCD_HC_GetXferCount(hhcd, chnum); + (obj->*func)(addr); + } else { + if (urb_state !=0) { + USB_DBG_EVENT("spurious %d %d",chnum, urb_state); + } + } +} + +USBHALHost * USBHALHost::instHost; + + +void USBHALHost::init() +{ + + NVIC_DisableIRQ(USBHAL_IRQn); + NVIC_SetVector(USBHAL_IRQn, (uint32_t)(_usbisr)); + HAL_HCD_Init((HCD_HandleTypeDef *) usb_hcca); + NVIC_EnableIRQ(USBHAL_IRQn); + control_disable = 0; + HAL_HCD_Start((HCD_HandleTypeDef *) usb_hcca); + usb_vbus(1); +} + +uint32_t USBHALHost::controlHeadED() +{ + return 0xffffffff; +} + +uint32_t USBHALHost::bulkHeadED() +{ + return 0xffffffff; +} + +uint32_t USBHALHost::interruptHeadED() +{ + return 0xffffffff; +} + +void USBHALHost::updateBulkHeadED(uint32_t addr) +{ +} + + +void USBHALHost::updateControlHeadED(uint32_t addr) +{ +} + +void USBHALHost::updateInterruptHeadED(uint32_t addr) +{ +} + + +void USBHALHost::enableList(ENDPOINT_TYPE type) +{ + /* react when the 3 lists are requested to be disabled */ + if (type == CONTROL_ENDPOINT) { + control_disable--; + if (control_disable == 0) { + NVIC_EnableIRQ(USBHAL_IRQn); + } else { + printf("reent\n"); + } + } +} + + +bool USBHALHost::disableList(ENDPOINT_TYPE type) +{ + if (type == CONTROL_ENDPOINT) { + NVIC_DisableIRQ(USBHAL_IRQn); + control_disable++; + if (control_disable > 1) { + printf("disable reentrance !!!\n"); + } + return true; + } + return false; +} + + +void USBHALHost::memInit() +{ + usb_hcca = (volatile HCD_HandleTypeDef *)usb_buf; + usb_edBuf = usb_buf + HCCA_SIZE; + usb_tdBuf = usb_buf + HCCA_SIZE +(MAX_ENDPOINT*ED_SIZE); + /* init channel */ + memset((void*)usb_buf,0, TOTAL_SIZE); + for (int i=0; i < MAX_ENDPOINT; i++) { + HCED *hced = (HCED*)(usb_edBuf + i*ED_SIZE); + hced->ch_num = i; + hced->hhcd = (HCCA *) usb_hcca; + } +} + +volatile uint8_t * USBHALHost::getED() +{ + for (int i = 0; i < MAX_ENDPOINT; i++) { + if ( !edBufAlloc[i] ) { + edBufAlloc[i] = true; + return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); + } + } + perror("Could not allocate ED\r\n"); + return NULL; //Could not alloc ED +} + +volatile uint8_t * USBHALHost::getTD() +{ + int i; + for (i = 0; i < MAX_TD; i++) { + if ( !tdBufAlloc[i] ) { + tdBufAlloc[i] = true; + return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); + } + } + perror("Could not allocate TD\r\n"); + return NULL; //Could not alloc TD +} + + +void USBHALHost::freeED(volatile uint8_t * ed) +{ + int i; + i = (ed - usb_edBuf) / ED_SIZE; + edBufAlloc[i] = false; +} + +void USBHALHost::freeTD(volatile uint8_t * td) +{ + int i; + i = (td - usb_tdBuf) / TD_SIZE; + tdBufAlloc[i] = false; +} + + +void USBHALHost::resetRootHub() +{ + // Initiate port reset + wait(0.2); + HAL_HCD_ResetPort((HCD_HandleTypeDef *)usb_hcca); +} + + +void USBHALHost::_usbisr(void) +{ + if (instHost) { + instHost->UsbIrqhandler(); + } +} + +void USBHALHost::UsbIrqhandler() +{ + HAL_HCD_IRQHandler((HCD_HandleTypeDef *)usb_hcca); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM/USBHALHost_STM_144_64pins.h Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,121 @@ +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef USBHALHOST_STM32_144_64 +#define USBHALHOST_STM32_144_64 + +#define USBHAL_IRQn OTG_FS_IRQn + +#define HCCA_SIZE sizeof(HCD_HandleTypeDef) +#define ED_SIZE sizeof(HCED) +#define TD_SIZE sizeof(HCTD) + +#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) +/* STM device FS have 11 channels (definition is for 60 channels) */ +static volatile uint8_t usb_buf[TOTAL_SIZE]; +typedef struct +{ + /* store the request ongoing on each endpoit */ + /* 1st field of structure avoid giving knowledge of all structure to + * endpoint */ + volatile uint32_t addr[MAX_ENDPOINT]; + USBHALHost *inst; + void (USBHALHost::*deviceConnected)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent); + void (USBHALHost::*deviceDisconnected)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr); + void (USBHALHost::*transferCompleted)(volatile uint32_t addr); +}USBHALHost_Private_t; + +/* CONFIGURATION for USB_VBUS + * on 64 bits board PC_0 is used (0 VBUS on, 1 VBUS off) + * on 144 pins board PG_6 is used ( 1 VBUS on, 0 VBUS on) + */ +static gpio_t gpio_vbus; + +#if defined(USBHALHOST_64pins) +#define VBUS_OFF 1 +#define VBUS_ON 0 +#define USB_VBUS_CONFIG \ + do {__HAL_RCC_GPIOC_CLK_ENABLE();\ + gpio_init_out_ex(&gpio_vbus, PC_0, VBUS_OFF);\ + }while(0); +#else +#define VBUS_OFF 0 +#define VBUS_ON 1 +#define USB_VBUS_CONFIG \ + do {__HAL_RCC_GPIOG_CLK_ENABLE();\ + gpio_init_out_ex(&gpio_vbus, PG_6, VBUS_OFF);\ + }while(0); +#endif + +void usb_vbus( uint8_t state) +{ + if(state == 0) + { + gpio_write(&gpio_vbus, VBUS_OFF); + } + else + { + gpio_write(&gpio_vbus, VBUS_ON); + } + wait(0.2); +} + +USBHALHost::USBHALHost() { + instHost = this; + HCD_HandleTypeDef *hhcd; + USBHALHost_Private_t *HALPriv = new(USBHALHost_Private_t); + memset(HALPriv, 0, sizeof(USBHALHost_Private_t)); + memInit(); + memset((void*)usb_hcca, 0, HCCA_SIZE); + hhcd = (HCD_HandleTypeDef *)usb_hcca; + hhcd->Instance = USB_OTG_FS; + hhcd->pData = (void*)HALPriv; + hhcd->Init.Host_channels = 11; + hhcd->Init.speed = HCD_SPEED_FULL; + hhcd->Init.phy_itface = HCD_PHY_EMBEDDED; + HALPriv->inst = this; + HALPriv->deviceConnected = &USBHALHost::deviceConnected; + HALPriv->deviceDisconnected = &USBHALHost::deviceDisconnected; + HALPriv->transferCompleted = &USBHALHost::transferCompleted; + for (int i = 0; i < MAX_ENDPOINT; i++) { + edBufAlloc[i] = false; + HALPriv->addr[i]=(uint32_t)-1; + } + for (int i = 0; i < MAX_TD; i++) { + tdBufAlloc[i] = false; + } + __HAL_RCC_PWR_CLK_ENABLE(); +#ifdef TARGET_STM32L4 + HAL_PWREx_EnableVddUSB(); +#endif + /* Configure USB FS GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /*USB DM and DP */ + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); + /*USB ID */ + pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + /* Configure POWER_SWITCH IO pin */ + USB_VBUS_CONFIG; + /* Enable USB FS Clocks */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Set USBFS Interrupt priority */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0); +} +#endif
--- a/USBHost/USBDeviceConnected.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBDeviceConnected.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -94,7 +94,7 @@ void USBDeviceConnected::disconnect() { for(int i = 0; i < MAX_INTF; i++) { - intf[i].detach.call(); + if (intf[i].detach) intf[i].detach.call(); } init(); }
--- a/USBHost/USBDeviceConnected.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBDeviceConnected.h Thu Jul 20 10:13:56 2017 +0100 @@ -21,6 +21,7 @@ #include "USBEndpoint.h" #include "USBHostConf.h" #include "rtos.h" +#include "Callback.h" class USBHostHub; @@ -31,7 +32,7 @@ uint8_t intf_subclass; uint8_t intf_protocol; USBEndpoint * ep[MAX_ENDPOINT_PER_INTERFACE]; - FunctionPointer detach; + Callback<void()> detach; char name[10]; } INTERFACE;
--- a/USBHost/USBEndpoint.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBEndpoint.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -17,7 +17,7 @@ #include "dbg.h" #include "USBEndpoint.h" - +#if !defined(USBHOST_OTHER) void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir_, uint32_t size, uint8_t ep_number, HCTD* td_list_[2]) { hced = hced_; @@ -76,6 +76,7 @@ hced->control &= ~(1 << 13); hced->control |= (speed << 13); } +#endif //Only for control Eps void USBEndpoint::setNextToken(uint32_t token) @@ -95,7 +96,6 @@ break; } } - struct { USB_TYPE type; const char * str; @@ -120,19 +120,18 @@ {USB_TYPE_PROCESSING, "USB_TYPE_PROCESSING"}, {USB_TYPE_ERROR, "USB_TYPE_ERROR"} }; +const char * USBEndpoint::getStateString() { + return type_string[state].str; +} +#if !defined(USBHOST_OTHER) void USBEndpoint::setState(uint8_t st) { if (st > 18) return; state = type_string[st].type; } - -const char * USBEndpoint::getStateString() { - return type_string[state].str; -} - -void USBEndpoint::queueTransfer() +USB_TYPE USBEndpoint::queueTransfer() { transfer_len = (uint32_t)td_current->bufEnd - (uint32_t)td_current->currBufPtr + 1; transferred = transfer_len; @@ -142,6 +141,7 @@ state = USB_TYPE_PROCESSING; td_current->nextTD = (hcTd*)td_next; hced->tailTD = td_next; + return USB_TYPE_PROCESSING; } void USBEndpoint::unqueueTransfer(volatile HCTD * td) @@ -160,3 +160,4 @@ nextEp = ed; hced->nextED = (ed == NULL) ? 0 : (hcEd*)(ed->getHCED()); } +#endif
--- a/USBHost/USBEndpoint.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBEndpoint.h Thu Jul 20 10:13:56 2017 +0100 @@ -17,7 +17,7 @@ #ifndef USBENDPOINT_H #define USBENDPOINT_H -#include "FunctionPointer.h" +#include "Callback.h" #include "USBHostTypes.h" #include "rtos.h" @@ -33,6 +33,9 @@ * Constructor */ USBEndpoint() { +#ifdef USBHOST_OTHER + speed = false; +#endif state = USB_TYPE_FREE; nextEp = NULL; }; @@ -47,6 +50,7 @@ * @param ep_number endpoint number * @param td_list array of two allocated transfer descriptors */ + void init(HCED * hced, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t ep_number, HCTD* td_list[2]); /** @@ -67,7 +71,7 @@ /** * Queue a transfer on the endpoint */ - void queueTransfer(); + USB_TYPE queueTransfer(); /** * Unqueue a transfer from the endpoint @@ -104,12 +108,17 @@ * Call the handler associted to the end of a transfer */ inline void call() { - rx.call(); + if (rx) + rx.call(); }; // setters +#ifdef USBHOST_OTHER + void setState(USB_TYPE st); +#else inline void setState(USB_TYPE st) { state = st; } +#endif void setState(uint8_t st); void setDeviceAddress(uint8_t addr); inline void setLengthTransferred(int len) { transferred = len; }; @@ -122,12 +131,17 @@ const char * getStateString(); inline USB_TYPE getState() { return state; } inline ENDPOINT_TYPE getType() { return type; }; +#ifdef USBHOST_OTHER + inline uint8_t getDeviceAddress() { return device_address; }; + inline uint32_t getSize() { return size; }; +#else inline uint8_t getDeviceAddress() { return hced->control & 0x7f; }; + inline uint32_t getSize() { return (hced->control >> 16) & 0x3ff; }; + inline volatile HCTD * getHeadTD() { return (volatile HCTD*) ((uint32_t)hced->headTD & ~0xF); }; +#endif inline int getLengthTransferred() { return transferred; } inline uint8_t * getBufStart() { return buf_start; } inline uint8_t getAddress(){ return address; }; - inline uint32_t getSize() { return (hced->control >> 16) & 0x3ff; }; - inline volatile HCTD * getHeadTD() { return (volatile HCTD*) ((uint32_t)hced->headTD & ~0xF); }; inline volatile HCTD** getTDList() { return td_list; }; inline volatile HCED * getHCED() { return hced; }; inline ENDPOINT_DIRECTION getDir() { return dir; } @@ -145,6 +159,12 @@ ENDPOINT_TYPE type; volatile USB_TYPE state; ENDPOINT_DIRECTION dir; +#ifdef USBHOST_OTHER + uint32_t size; + uint32_t ep_number; + uint32_t speed; + uint8_t device_address; +#endif bool setup; uint8_t address; @@ -153,7 +173,7 @@ int transferred; uint8_t * buf_start; - FunctionPointer rx; + Callback<void()> rx; USBEndpoint* nextEp;
--- a/USBHost/USBHALHost.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBHALHost.h Thu Jul 20 10:13:56 2017 +0100 @@ -164,6 +164,10 @@ bool volatile edBufAlloc[MAX_ENDPOINT]; bool volatile tdBufAlloc[MAX_TD]; +#ifdef USBHOST_OTHER + int control_disable; +#endif + }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_M451.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,347 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(TARGET_M451) + +#include "mbed.h" +#include "USBHALHost.h" +#include "dbg.h" +#include "pinmap.h" + +#define HCCA_SIZE sizeof(HCCA) +#define ED_SIZE sizeof(HCED) +#define TD_SIZE sizeof(HCTD) + +#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) + +#ifndef USBH_HcRhDescriptorA_POTPGT_Pos +#define USBH_HcRhDescriptorA_POTPGT_Pos (24) +#endif +#ifndef USBH_HcRhDescriptorA_POTPGT_Msk +#define USBH_HcRhDescriptorA_POTPGT_Msk (0xfful << USBH_HcRhDescriptorA_POTPGT_Pos) +#endif + +static volatile MBED_ALIGN(256) uint8_t usb_buf[TOTAL_SIZE]; // 256 bytes aligned! + +USBHALHost * USBHALHost::instHost; + +USBHALHost::USBHALHost() +{ + instHost = this; + memInit(); + memset((void*)usb_hcca, 0, HCCA_SIZE); + for (int i = 0; i < MAX_ENDPOINT; i++) { + edBufAlloc[i] = false; + } + for (int i = 0; i < MAX_TD; i++) { + tdBufAlloc[i] = false; + } +} + +void USBHALHost::init() +{ + // Unlock protected registers + SYS_UnlockReg(); + + // Enable USBH clock + CLK_EnableModuleClock(USBH_MODULE); + // Set USBH clock source/divider + CLK_SetModuleClock(USBH_MODULE, 0, CLK_CLKDIV0_USB(3)); + + // Configure OTG function as Host-Only + SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk | SYS_USBPHY_USBROLE_STD_USBH; + + /* Below settings is use power switch IC to enable/disable USB Host power. + Set PA.2 is VBUS_EN function pin and PA.3 VBUS_ST function pin */ + pin_function(PA_3, SYS_GPA_MFPL_PA3MFP_USB_VBUS_ST); + pin_function(PA_2, SYS_GPA_MFPL_PA2MFP_USB_VBUS_EN); + + // Enable OTG clock + CLK_EnableModuleClock(OTG_MODULE); + + // Lock protected registers + SYS_LockReg(); + + // Overcurrent flag is low active + USBH->HcMiscControl |= USBH_HcMiscControl_OCAL_Msk; + + // Disable HC interrupts + USBH->HcInterruptDisable = OR_INTR_ENABLE_MIE; + + // Needed by some controllers + USBH->HcControl = 0; + + // Software reset + USBH->HcCommandStatus = OR_CMD_STATUS_HCR; + while (USBH->HcCommandStatus & OR_CMD_STATUS_HCR); + + // Put HC in reset state + USBH->HcControl = (USBH->HcControl & ~OR_CONTROL_HCFS) | OR_CONTROL_HC_RSET; + // HCD must wait 10ms for HC reset complete + wait_ms(100); + + USBH->HcControlHeadED = 0; // Initialize Control ED list head to 0 + USBH->HcBulkHeadED = 0; // Initialize Bulk ED list head to 0 + USBH->HcHCCA = (uint32_t) usb_hcca; + + USBH->HcFmInterval = DEFAULT_FMINTERVAL; // Frame interval = 12000 - 1 + // MPS = 10,104 + USBH->HcPeriodicStart = FI * 90 / 100; // 90% of frame interval + USBH->HcLSThreshold = 0x628; // Low speed threshold + + // Put HC in operational state + USBH->HcControl = (USBH->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; + + // FIXME + USBH->HcRhDescriptorA = USBH->HcRhDescriptorA & ~(USBH_HcRhDescriptorA_NOCP_Msk | USBH_HcRhDescriptorA_OCPM_Msk | USBH_HcRhDescriptorA_PSM_Msk); + // Issue SetGlobalPower command + USBH->HcRhStatus = USBH_HcRhStatus_LPSC_Msk; + // Power On To Power Good Time, in 2 ms units + wait_ms(((USBH->HcRhDescriptorA & USBH_HcRhDescriptorA_POTPGT_Msk) >> USBH_HcRhDescriptorA_POTPGT_Pos) * 2); + + // Clear Interrrupt Status + USBH->HcInterruptStatus |= USBH->HcInterruptStatus; + // Enable interrupts we care about + USBH->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; + + NVIC_SetVector(USBH_IRQn, (uint32_t)(_usbisr)); + NVIC_EnableIRQ(USBH_IRQn); + + // Check for any connected devices + if (USBH->HcRhPortStatus[0] & OR_RH_PORT_CCS) { + // Device connected + wait_ms(150); + deviceConnected(0, 1, USBH->HcRhPortStatus[0] & OR_RH_PORT_LSDA); + } +} + +uint32_t USBHALHost::controlHeadED() +{ + return USBH->HcControlHeadED; +} + +uint32_t USBHALHost::bulkHeadED() +{ + return USBH->HcBulkHeadED; +} + +uint32_t USBHALHost::interruptHeadED() +{ + // FIXME: Only support one INT ED? + return usb_hcca->IntTable[0]; +} + +void USBHALHost::updateBulkHeadED(uint32_t addr) +{ + USBH->HcBulkHeadED = addr; +} + + +void USBHALHost::updateControlHeadED(uint32_t addr) +{ + USBH->HcControlHeadED = addr; +} + +void USBHALHost::updateInterruptHeadED(uint32_t addr) +{ + // FIXME: Only support one INT ED? + usb_hcca->IntTable[0] = addr; +} + + +void USBHALHost::enableList(ENDPOINT_TYPE type) +{ + switch(type) { + case CONTROL_ENDPOINT: + USBH->HcCommandStatus = OR_CMD_STATUS_CLF; + USBH->HcControl |= OR_CONTROL_CLE; + break; + case ISOCHRONOUS_ENDPOINT: + // FIXME + break; + case BULK_ENDPOINT: + USBH->HcCommandStatus = OR_CMD_STATUS_BLF; + USBH->HcControl |= OR_CONTROL_BLE; + break; + case INTERRUPT_ENDPOINT: + USBH->HcControl |= OR_CONTROL_PLE; + break; + } +} + + +bool USBHALHost::disableList(ENDPOINT_TYPE type) +{ + switch(type) { + case CONTROL_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_CLE) { + USBH->HcControl &= ~OR_CONTROL_CLE; + return true; + } + return false; + case ISOCHRONOUS_ENDPOINT: + // FIXME + return false; + case BULK_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_BLE){ + USBH->HcControl &= ~OR_CONTROL_BLE; + return true; + } + return false; + case INTERRUPT_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_PLE) { + USBH->HcControl &= ~OR_CONTROL_PLE; + return true; + } + return false; + } + return false; +} + + +void USBHALHost::memInit() +{ + usb_hcca = (volatile HCCA *)usb_buf; + usb_edBuf = usb_buf + HCCA_SIZE; + usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE); +} + +volatile uint8_t * USBHALHost::getED() +{ + for (int i = 0; i < MAX_ENDPOINT; i++) { + if ( !edBufAlloc[i] ) { + edBufAlloc[i] = true; + return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); + } + } + perror("Could not allocate ED\r\n"); + return NULL; //Could not alloc ED +} + +volatile uint8_t * USBHALHost::getTD() +{ + int i; + for (i = 0; i < MAX_TD; i++) { + if ( !tdBufAlloc[i] ) { + tdBufAlloc[i] = true; + return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); + } + } + perror("Could not allocate TD\r\n"); + return NULL; //Could not alloc TD +} + + +void USBHALHost::freeED(volatile uint8_t * ed) +{ + int i; + i = (ed - usb_edBuf) / ED_SIZE; + edBufAlloc[i] = false; +} + +void USBHALHost::freeTD(volatile uint8_t * td) +{ + int i; + i = (td - usb_tdBuf) / TD_SIZE; + tdBufAlloc[i] = false; +} + + +void USBHALHost::resetRootHub() +{ + // Reset port1 + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRS; + while (USBH->HcRhPortStatus[0] & OR_RH_PORT_PRS); + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC; +} + + +void USBHALHost::_usbisr(void) +{ + if (instHost) { + instHost->UsbIrqhandler(); + } +} + +void USBHALHost::UsbIrqhandler() +{ + uint32_t ints = USBH->HcInterruptStatus; + + // Root hub status change interrupt + if (ints & OR_INTR_STATUS_RHSC) { + uint32_t ints_roothub = USBH->HcRhStatus; + uint32_t ints_port1 = USBH->HcRhPortStatus[0]; + uint32_t ints_port2 = USBH->HcRhPortStatus[1]; + + // Port1: ConnectStatusChange + if (ints_port1 & OR_RH_PORT_CSC) { + if (ints_roothub & OR_RH_STATUS_DRWE) { + // When DRWE is on, Connect Status Change means a remote wakeup event. + } else { + if (ints_port1 & OR_RH_PORT_CCS) { + // Root device connected + + // wait 150ms to avoid bounce + wait_ms(150); + + //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed + deviceConnected(0, 1, ints_port1 & OR_RH_PORT_LSDA); + } else { + // Root device disconnected + + if (!(ints & OR_INTR_STATUS_WDH)) { + usb_hcca->DoneHead = 0; + } + + // wait 200ms to avoid bounce + wait_ms(200); + + deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); + + if (ints & OR_INTR_STATUS_WDH) { + usb_hcca->DoneHead = 0; + USBH->HcInterruptStatus = OR_INTR_STATUS_WDH; + } + } + } + USBH->HcRhPortStatus[0] = OR_RH_PORT_CSC; + } + // Port1: Reset completed + if (ints_port1 & OR_RH_PORT_PRSC) { + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC; + } + // Port1: PortEnableStatusChange + if (ints_port1 & OR_RH_PORT_PESC) { + USBH->HcRhPortStatus[0] = OR_RH_PORT_PESC; + } + + // Port2: PortOverCurrentIndicatorChange + if (ints_port2 & OR_RH_PORT_OCIC) { + USBH->HcRhPortStatus[1] = OR_RH_PORT_OCIC; + } + + USBH->HcInterruptStatus = OR_INTR_STATUS_RHSC; + } + + // Writeback Done Head interrupt + if (ints & OR_INTR_STATUS_WDH) { + transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE); + USBH->HcInterruptStatus = OR_INTR_STATUS_WDH; + } + + +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_NUC472.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -0,0 +1,365 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(TARGET_NUC472) + +#include "mbed.h" +#include "USBHALHost.h" +#include "dbg.h" +#include "pinmap.h" + +#define HCCA_SIZE sizeof(HCCA) +#define ED_SIZE sizeof(HCED) +#define TD_SIZE sizeof(HCTD) + +#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) + +static volatile MBED_ALIGN(256) uint8_t usb_buf[TOTAL_SIZE]; // 256 bytes aligned! + +USBHALHost * USBHALHost::instHost; + +USBHALHost::USBHALHost() +{ + instHost = this; + memInit(); + memset((void*)usb_hcca, 0, HCCA_SIZE); + for (int i = 0; i < MAX_ENDPOINT; i++) { + edBufAlloc[i] = false; + } + for (int i = 0; i < MAX_TD; i++) { + tdBufAlloc[i] = false; + } +} + +void USBHALHost::init() +{ + // Unlock protected registers + SYS_UnlockReg(); + + // NOTE: Configure as OTG device first; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below. + SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk | SYS_USBPHY_USBROLE_ON_THE_GO; + + // NOTE: Enable OTG here; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below. + CLK_EnableModuleClock(OTG_MODULE); + OTG->PHYCTL = (OTG->PHYCTL | OTG_PHYCTL_OTGPHYEN_Msk) & ~OTG_PHYCTL_IDDETEN_Msk; + //OTG->CTL |= OTG_CTL_OTGEN_Msk | OTG_CTL_BUSREQ_Msk; + + // PB.0: USB0 external VBUS regulator status + // USB_OC + // PB.1: USB0 external VBUS regulator enable + // NCT3520U low active (USB_PWR_EN) + pin_function(PB_0, SYS_GPB_MFPL_PB0MFP_USB0_OTG5V_ST); + pin_function(PB_1, SYS_GPB_MFPL_PB1MFP_USB0_OTG5V_EN); + + // PB.2: USB1 differential signal D- + // PB.3: USB1 differential signal D+ + //pin_function(PB_2, SYS_GPB_MFPL_PB2MFP_USB1_D_N); + //pin_function(PB_3, SYS_GPB_MFPL_PB3MFP_USB1_D_P); + + // Set PB.4 output high to enable USB power + //gpio_t gpio; + //gpio_init_out_ex(&gpio, PB_4, 1); + + // NOTE: + // 1. Set USBH clock source to PLL2; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below. + // 2. Don't set CLK_PLL2CTL_PLL2CKEN_Msk. USBH will work abnormally with it enabled. + CLK->CLKSEL0 &= ~CLK_CLKSEL0_USBHSEL_Msk; + // Enable PLL2, 480 MHz / 2 / (1+4) => 48 MHz output + CLK->PLL2CTL = /*CLK_PLL2CTL_PLL2CKEN_Msk | */ (4 << CLK_PLL2CTL_PLL2DIV_Pos); + // Wait PLL2 stable ... + while (!(CLK->STATUS & CLK_STATUS_PLL2STB_Msk)); + + // Select USB Host clock source from PLL2, clock divied by 1 + CLK_SetModuleClock(USBH_MODULE, CLK_CLKSEL0_USBHSEL_PLL2, CLK_CLKDIV0_USB(1)); + + // Enable USB Host clock + CLK_EnableModuleClock(USBH_MODULE); + + // Lock protected registers + SYS_LockReg(); + + // Overcurrent flag is high active + USBH->HcMiscControl &= ~USBH_HcMiscControl_OCAL_Msk; + + // Disable HC interrupts + USBH->HcInterruptDisable = OR_INTR_ENABLE_MIE; + + // Needed by some controllers + USBH->HcControl = 0; + + // Software reset + USBH->HcCommandStatus = OR_CMD_STATUS_HCR; + while (USBH->HcCommandStatus & OR_CMD_STATUS_HCR); + + // Put HC in reset state + USBH->HcControl = (USBH->HcControl & ~OR_CONTROL_HCFS) | OR_CONTROL_HC_RSET; + // HCD must wait 10ms for HC reset complete + wait_ms(100); + + USBH->HcControlHeadED = 0; // Initialize Control ED list head to 0 + USBH->HcBulkHeadED = 0; // Initialize Bulk ED list head to 0 + USBH->HcHCCA = (uint32_t) usb_hcca; + + USBH->HcFmInterval = DEFAULT_FMINTERVAL; // Frame interval = 12000 - 1 + // MPS = 10,104 + USBH->HcPeriodicStart = FI * 90 / 100; // 90% of frame interval + USBH->HcLSThreshold = 0x628; // Low speed threshold + + // Put HC in operational state + USBH->HcControl = (USBH->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; + + // FIXME: Ports are power switched. All ports are powered at the same time. Doesn't match BSP sample. + USBH->HcRhDescriptorA = USBH->HcRhDescriptorA & ~USBH_HcRhDescriptorA_NPS_Msk & ~USBH_HcRhDescriptorA_PSM_Msk; + // Issue SetGlobalPower command + USBH->HcRhStatus = USBH_HcRhStatus_LPSC_Msk; + // Power On To Power Good Time, in 2 ms units + wait_ms(((USBH->HcRhDescriptorA & USBH_HcRhDescriptorA_POTPGT_Msk) >> USBH_HcRhDescriptorA_POTPGT_Pos) * 2); + + // Clear Interrrupt Status + USBH->HcInterruptStatus |= USBH->HcInterruptStatus; + // Enable interrupts we care about + USBH->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; + + + // Unlock protected registers + SYS_UnlockReg(); + + // NOTE: Configure as USB host after USBH init above; otherwise system will crash. + SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_USBROLE_STD_USBH; + + // Lock protected registers + SYS_LockReg(); + + NVIC_SetVector(USBH_IRQn, (uint32_t)(_usbisr)); + NVIC_EnableIRQ(USBH_IRQn); + + // Check for any connected devices + if (USBH->HcRhPortStatus[0] & OR_RH_PORT_CCS) { + // Device connected + wait_ms(150); + deviceConnected(0, 1, USBH->HcRhPortStatus[0] & OR_RH_PORT_LSDA); + } +} + +uint32_t USBHALHost::controlHeadED() +{ + return USBH->HcControlHeadED; +} + +uint32_t USBHALHost::bulkHeadED() +{ + return USBH->HcBulkHeadED; +} + +uint32_t USBHALHost::interruptHeadED() +{ + // FIXME: Only support one INT ED? + return usb_hcca->IntTable[0]; +} + +void USBHALHost::updateBulkHeadED(uint32_t addr) +{ + USBH->HcBulkHeadED = addr; +} + + +void USBHALHost::updateControlHeadED(uint32_t addr) +{ + USBH->HcControlHeadED = addr; +} + +void USBHALHost::updateInterruptHeadED(uint32_t addr) +{ + // FIXME: Only support one INT ED? + usb_hcca->IntTable[0] = addr; +} + + +void USBHALHost::enableList(ENDPOINT_TYPE type) +{ + switch(type) { + case CONTROL_ENDPOINT: + USBH->HcCommandStatus = OR_CMD_STATUS_CLF; + USBH->HcControl |= OR_CONTROL_CLE; + break; + case ISOCHRONOUS_ENDPOINT: + // FIXME + break; + case BULK_ENDPOINT: + USBH->HcCommandStatus = OR_CMD_STATUS_BLF; + USBH->HcControl |= OR_CONTROL_BLE; + break; + case INTERRUPT_ENDPOINT: + USBH->HcControl |= OR_CONTROL_PLE; + break; + } +} + + +bool USBHALHost::disableList(ENDPOINT_TYPE type) +{ + switch(type) { + case CONTROL_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_CLE) { + USBH->HcControl &= ~OR_CONTROL_CLE; + return true; + } + return false; + case ISOCHRONOUS_ENDPOINT: + // FIXME + return false; + case BULK_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_BLE){ + USBH->HcControl &= ~OR_CONTROL_BLE; + return true; + } + return false; + case INTERRUPT_ENDPOINT: + if(USBH->HcControl & OR_CONTROL_PLE) { + USBH->HcControl &= ~OR_CONTROL_PLE; + return true; + } + return false; + } + return false; +} + + +void USBHALHost::memInit() +{ + usb_hcca = (volatile HCCA *)usb_buf; + usb_edBuf = usb_buf + HCCA_SIZE; + usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE); +} + +volatile uint8_t * USBHALHost::getED() +{ + for (int i = 0; i < MAX_ENDPOINT; i++) { + if ( !edBufAlloc[i] ) { + edBufAlloc[i] = true; + return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); + } + } + perror("Could not allocate ED\r\n"); + return NULL; //Could not alloc ED +} + +volatile uint8_t * USBHALHost::getTD() +{ + int i; + for (i = 0; i < MAX_TD; i++) { + if ( !tdBufAlloc[i] ) { + tdBufAlloc[i] = true; + return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); + } + } + perror("Could not allocate TD\r\n"); + return NULL; //Could not alloc TD +} + + +void USBHALHost::freeED(volatile uint8_t * ed) +{ + int i; + i = (ed - usb_edBuf) / ED_SIZE; + edBufAlloc[i] = false; +} + +void USBHALHost::freeTD(volatile uint8_t * td) +{ + int i; + i = (td - usb_tdBuf) / TD_SIZE; + tdBufAlloc[i] = false; +} + + +void USBHALHost::resetRootHub() +{ + // Reset port1 + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRS; + while (USBH->HcRhPortStatus[0] & OR_RH_PORT_PRS); + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC; +} + + +void USBHALHost::_usbisr(void) +{ + if (instHost) { + instHost->UsbIrqhandler(); + } +} + +void USBHALHost::UsbIrqhandler() +{ + uint32_t ints = USBH->HcInterruptStatus; + + // Root hub status change interrupt + if (ints & OR_INTR_STATUS_RHSC) { + uint32_t ints_roothub = USBH->HcRhStatus; + uint32_t ints_port1 = USBH->HcRhPortStatus[0]; + + // Port1: ConnectStatusChange + if (ints_port1 & OR_RH_PORT_CSC) { + if (ints_roothub & OR_RH_STATUS_DRWE) { + // When DRWE is on, Connect Status Change means a remote wakeup event. + } else { + if (ints_port1 & OR_RH_PORT_CCS) { + // Root device connected + + // wait 150ms to avoid bounce + wait_ms(150); + + //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed + deviceConnected(0, 1, ints_port1 & OR_RH_PORT_LSDA); + } else { + // Root device disconnected + + if (!(ints & OR_INTR_STATUS_WDH)) { + usb_hcca->DoneHead = 0; + } + + // wait 200ms to avoid bounce + wait_ms(200); + + deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); + + if (ints & OR_INTR_STATUS_WDH) { + usb_hcca->DoneHead = 0; + USBH->HcInterruptStatus = OR_INTR_STATUS_WDH; + } + } + } + USBH->HcRhPortStatus[0] = OR_RH_PORT_CSC; + } + // Port1: Reset completed + if (ints_port1 & OR_RH_PORT_PRSC) { + USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC; + } + // Port1: PortEnableStatusChange + if (ints_port1 & OR_RH_PORT_PESC) { + USBH->HcRhPortStatus[0] = OR_RH_PORT_PESC; + } + + USBH->HcInterruptStatus = OR_INTR_STATUS_RHSC; + } + + // Writeback Done Head interrupt + if (ints & OR_INTR_STATUS_WDH) { + transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE); + USBH->HcInterruptStatus = OR_INTR_STATUS_WDH; + } +} +#endif
--- a/USBHost/USBHost.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBHost.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -46,7 +46,8 @@ * - when the usb_thread receives the event, it: * - call the callback attached to the endpoint where the td is attached */ -void USBHost::usb_process() { +void USBHost::usb_process() +{ bool controlListState; bool bulkListState; @@ -79,110 +80,130 @@ too_many_hub = false; buf[4] = 0; - do - { - Lock lock(this); + do { + Lock lock(this); + bool hub_unplugged = true; - for (i = 0; i < MAX_DEVICE_CONNECTED; i++) { - if (!deviceInUse[i]) { - USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]); - devices[i].init(usb_msg->hub, usb_msg->port, usb_msg->lowSpeed); - deviceReset[i] = false; - deviceInited[i] = true; - break; - } - } + int idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); + /* check that hub is connected to root port */ + if (usb_msg->hub_parent) { + /* a hub device must be present */ + for (k = 0; k < MAX_HUB_NB; k++) { + if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) { + hub_unplugged=false; + } + } + } else { + hub_unplugged = false; + } - if (i == MAX_DEVICE_CONNECTED) { - USB_ERR("Too many device connected!!\r\n"); - continue; - } + if (((idx!=-1) && deviceInUse[idx] ) || ((idx == -1) && hub_unplugged)) { + break; + } - if (!controlEndpointAllocated) { - control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); - addEndpoint(NULL, 0, (USBEndpoint*)control); - controlEndpointAllocated = true; - } + for (i =0 ; i < MAX_DEVICE_CONNECTED; i++) { + if (!deviceInUse[i]) { + USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]); + devices[i].init(usb_msg->hub, usb_msg->port, usb_msg->lowSpeed); + deviceReset[i] = false; + deviceInited[i] = true; + break; + } + } - #if MAX_HUB_NB - if (usb_msg->hub_parent) - devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent)); - #endif + if (i == MAX_DEVICE_CONNECTED) { + USB_ERR("Too many device connected!!\r\n"); + continue; + } - for (j = 0; j < timeout_set_addr; j++) { - - resetDevice(&devices[i]); - - // set size of control endpoint - devices[i].setSizeControlEndpoint(8); + if (!controlEndpointAllocated) { + control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); + addEndpoint(NULL, 0, (USBEndpoint*)control); + controlEndpointAllocated = true; + } - devices[i].activeAddress(false); +#if MAX_HUB_NB + if (usb_msg->hub_parent) { + devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent)); + } +#endif - // get first 8 bit of device descriptor - // and check if we deal with a hub - USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]); - res = getDeviceDescriptor(&devices[i], buf, 8); + for (j = 0; j < timeout_set_addr; j++) { + + resetDevice(&devices[i]); - if (res != USB_TYPE_OK) { - USB_ERR("usb_thread could not read dev descr"); - continue; - } + // set size of control endpoint + devices[i].setSizeControlEndpoint(8); + + devices[i].activeAddress(false); - // set size of control endpoint - devices[i].setSizeControlEndpoint(buf[7]); + // get first 8 bit of device descriptor + // and check if we deal with a hub + USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]); + res = getDeviceDescriptor(&devices[i], buf, 8); - // second step: set an address to the device - res = setAddress(&devices[i], devices[i].getAddress()); + if (res != USB_TYPE_OK) { + USB_ERR("usb_thread could not read dev descr"); + continue; + } - if (res != USB_TYPE_OK) { - USB_ERR("SET ADDR FAILED"); - continue; - } - devices[i].activeAddress(true); - USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress()); + // set size of control endpoint + devices[i].setSizeControlEndpoint(buf[7]); + + // second step: set an address to the device + res = setAddress(&devices[i], devices[i].getAddress()); - // try to read again the device descriptor to check if the device - // answers to its new address - res = getDeviceDescriptor(&devices[i], buf, 8); + if (res != USB_TYPE_OK) { + USB_ERR("SET ADDR FAILED"); + continue; + } + devices[i].activeAddress(true); + USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress()); - if (res == USB_TYPE_OK) { - break; - } + // try to read again the device descriptor to check if the device + // answers to its new address + res = getDeviceDescriptor(&devices[i], buf, 8); - Thread::wait(100); - } + if (res == USB_TYPE_OK) { + break; + } - USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port); + Thread::wait(100); + } + + USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port); - #if MAX_HUB_NB - if (buf[4] == HUB_CLASS) { - for (k = 0; k < MAX_HUB_NB; k++) { - if (hub_in_use[k] == false) { - for (uint8_t j = 0; j < MAX_TRY_ENUMERATE_HUB; j++) { - if (hubs[k].connect(&devices[i])) { - devices[i].hub = &hubs[k]; - hub_in_use[k] = true; - break; - } - } - if (hub_in_use[k] == true) - break; - } - } +#if MAX_HUB_NB + if (buf[4] == HUB_CLASS) { + for (k = 0; k < MAX_HUB_NB; k++) { + if (hub_in_use[k] == false) { + for (uint8_t j = 0; j < MAX_TRY_ENUMERATE_HUB; j++) { + if (hubs[k].connect(&devices[i])) { + devices[i].hub = &hubs[k]; + hub_in_use[k] = true; + break; + } + } + if (hub_in_use[k] == true) { + break; + } + } + } - if (k == MAX_HUB_NB) { - USB_ERR("Too many hubs connected!!\r\n"); - too_many_hub = true; - } - } + if (k == MAX_HUB_NB) { + USB_ERR("Too many hubs connected!!\r\n"); + too_many_hub = true; + } + } - if (usb_msg->hub_parent) - ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]); - #endif + if (usb_msg->hub_parent) { + ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]); + } +#endif - if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) { - deviceInUse[i] = true; - } + if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) { + deviceInUse[i] = true; + } } while(0); @@ -191,22 +212,28 @@ // a device has been disconnected case DEVICE_DISCONNECTED_EVENT: - do - { - Lock lock(this); + do { + Lock lock(this); - controlListState = disableList(CONTROL_ENDPOINT); - bulkListState = disableList(BULK_ENDPOINT); - interruptListState = disableList(INTERRUPT_ENDPOINT); + controlListState = disableList(CONTROL_ENDPOINT); + bulkListState = disableList(BULK_ENDPOINT); + interruptListState = disableList(INTERRUPT_ENDPOINT); - idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); - if (idx != -1) { - freeDevice((USBDeviceConnected*)&devices[idx]); - } + idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); + if (idx != -1) { + freeDevice((USBDeviceConnected*)&devices[idx]); + deviceInited[idx]=false; + } - if (controlListState) enableList(CONTROL_ENDPOINT); - if (bulkListState) enableList(BULK_ENDPOINT); - if (interruptListState) enableList(INTERRUPT_ENDPOINT); + if (controlListState) { + enableList(CONTROL_ENDPOINT); + } + if (bulkListState) { + enableList(BULK_ENDPOINT); + } + if (interruptListState) { + enableList(INTERRUPT_ENDPOINT); + } } while(0); @@ -224,8 +251,9 @@ if (ep->getDir() == IN) { buf_transfer = ep->getBufStart(); printf("READ SUCCESS [%d bytes transferred - td: 0x%08X] on ep: [%p - addr: %02X]: ", ep->getLengthTransferred(), usb_msg->td_addr, ep, ep->getAddress()); - for (int i = 0; i < ep->getLengthTransferred(); i++) + for (int i = 0; i < ep->getLengthTransferred(); i++) { printf("%02X ", buf_transfer[i]); + } printf("\r\n\r\n"); } #endif @@ -236,6 +264,12 @@ if (deviceInUse[idx]) { USB_WARN("td %p processed but not in idle state: %s [ep: %p - dev: %p - %s]", usb_msg->td_addr, ep->getStateString(), ep, ep->dev, ep->dev->getName(ep->getIntfNb())); ep->setState(USB_TYPE_IDLE); + /* as error, on interrupt endpoint can be + * reported, call the call back registered , + * if device still in use, this call back + * shall ask again an interrupt request. + */ + ep->call(); } } } @@ -247,19 +281,16 @@ } } -/* static */void USBHost::usb_process_static(void const * arg) { - ((USBHost *)arg)->usb_process(); -} - -USBHost::USBHost() : usbThread(USBHost::usb_process_static, (void *)this, osPriorityNormal, USB_THREAD_STACK) +USBHost::USBHost() : usbThread(osPriorityNormal, USB_THREAD_STACK) { +#ifndef USBHOST_OTHER headControlEndpoint = NULL; headBulkEndpoint = NULL; headInterruptEndpoint = NULL; tailControlEndpoint = NULL; tailBulkEndpoint = NULL; tailInterruptEndpoint = NULL; - +#endif lenReportDescr = 0; controlEndpointAllocated = false; @@ -269,8 +300,9 @@ devices[i].setAddress(i + 1); deviceReset[i] = false; deviceInited[i] = false; - for (uint8_t j = 0; j < MAX_INTF; j++) + for (uint8_t j = 0; j < MAX_INTF; j++) { deviceAttachedDriver[i][j] = false; + } } #if MAX_HUB_NB @@ -279,24 +311,27 @@ hub_in_use[i] = false; } #endif + + usbThread.start(this, &USBHost::usb_process); } USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost) { - m_pHost->usb_mutex.lock(); + m_pHost->usb_mutex.lock(); } USBHost::Lock::~Lock() { - m_pHost->usb_mutex.unlock(); + m_pHost->usb_mutex.unlock(); } void USBHost::transferCompleted(volatile uint32_t addr) { uint8_t state; - if(addr == 0) + if(addr == 0) { return; + } volatile HCTD* tdList = NULL; @@ -314,13 +349,25 @@ if (td->ep != NULL) { USBEndpoint * ep = (USBEndpoint *)(td->ep); +#ifdef USBHOST_OTHER + state = ((HCTD *)td)->state; + if (state == USB_TYPE_IDLE) { + ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); + } + +#else if (((HCTD *)td)->control >> 28) { state = ((HCTD *)td)->control >> 28; } else { - if (td->currBufPtr) + if (td->currBufPtr) { ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); + } state = 16 /*USB_TYPE_IDLE*/; } +#endif + if (state == USB_TYPE_IDLE) { + ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); + } ep->unqueueTransfer(td); @@ -332,7 +379,7 @@ usb_msg->td_state = state; mail_usb_event.put(usb_msg); } - ep->setState(state); + ep->setState((USB_TYPE)state); ep->ep_queue.put((uint8_t*)1); } } @@ -357,8 +404,9 @@ // be sure that the new device connected is not already connected... int idx = findDevice(hub, port, hub_parent); if (idx != -1) { - if (deviceInited[idx]) + if (deviceInited[idx]) { return; + } } message_t * usb_msg = mail_usb_event.alloc(); @@ -379,8 +427,9 @@ // be sure that the device disconnected is connected... int idx = findDevice(hub, port, hub_parent); if (idx != -1) { - if (!deviceInUse[idx]) + if (!deviceInUse[idx]) { return; + } } else { return; } @@ -414,8 +463,9 @@ } // notify hub parent that this device has been disconnected - if (dev->getHubParent()) + if (dev->getHubParent()) { dev->getHubParent()->deviceDisconnected(dev); + } #endif @@ -430,8 +480,10 @@ USB_DBG("FREE INTF %d on dev: %p, %p, nb_endpot: %d, %s", j, (void *)dev->getInterface(j), dev, dev->getInterface(j)->nb_endpoint, dev->getName(j)); for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) { if ((ep = dev->getEndpoint(j, i)) != NULL) { +#ifndef USBHOST_OTHER ed = (HCED *)ep->getHCED(); ed->control |= (1 << 14); //sKip bit +#endif unqueueEndpoint(ep); freeTD((volatile uint8_t*)ep->getTDList()[0]); @@ -452,6 +504,9 @@ void USBHost::unqueueEndpoint(USBEndpoint * ep) { +#ifdef USBHOST_OTHER + ep->setState(USB_TYPE_FREE); +#else USBEndpoint * prec = NULL; USBEndpoint * current = NULL; @@ -501,6 +556,7 @@ current = current->nextEndpoint(); } } +#endif } @@ -565,8 +621,10 @@ return false; } +#ifndef USBHOST_OTHER HCED * prevEd; +#endif // set device address in the USBEndpoint descriptor if (dev == NULL) { ep->setDeviceAddress(0); @@ -580,6 +638,7 @@ ep->setIntfNb(intf_nb); +#ifndef USBHOST_OTHER // queue the new USBEndpoint on the ED list switch (ep->getType()) { @@ -627,6 +686,7 @@ return false; } +#endif ep->dev = dev; dev->addEndpoint(intf_nb, ep); @@ -649,8 +709,9 @@ for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) { if (devices[i].getHub() == hub && devices[i].getPort() == port) { if (hub_parent != NULL) { - if (hub_parent == devices[i].getHubParent()) + if (hub_parent == devices[i].getHubParent()) { return i; + } } else { return i; } @@ -661,7 +722,7 @@ void USBHost::printList(ENDPOINT_TYPE type) { -#if DEBUG_EP_STATE +#if defined(DEBUG_EP_STATE) && !defined(USBHOST_OTHER) volatile HCED * hced; switch(type) { case CONTROL_ENDPOINT: @@ -677,14 +738,14 @@ volatile HCTD * hctd = NULL; const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : - ((type == CONTROL_ENDPOINT) ? "CONTROL" : "ISOCHRONOUS")); + ((type == CONTROL_ENDPOINT) ? "CONTROL" : "ISOCHRONOUS")); printf("State of %s:\r\n", type_str); while (hced != NULL) { uint8_t dir = ((hced->control & (3 << 11)) >> 11); printf("hced: %p [ADDR: %d, DIR: %s, EP_NB: 0x%X]\r\n", hced, - hced->control & 0x7f, - (dir == 1) ? "OUT" : ((dir == 0) ? "FROM_TD":"IN"), - (hced->control & (0xf << 7)) >> 7); + hced->control & 0x7f, + (dir == 1) ? "OUT" : ((dir == 0) ? "FROM_TD":"IN"), + (hced->control & (0xf << 7)) >> 7); hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0xf)); while (hctd != hced->tailTD) { printf("\thctd: %p [DIR: %s]\r\n", hctd, ((hctd->control & (3 << 19)) >> 19) == 1 ? "OUT" : "IN"); @@ -701,6 +762,7 @@ // add a transfer on the TD linked list USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) { + USB_TYPE ret=USB_TYPE_PROCESSING; td_mutex.lock(); // allocate a TD which will be freed in TDcompletion @@ -709,6 +771,7 @@ return USB_TYPE_ERROR; } +#ifndef USBHOST_OTHER uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT )); uint32_t td_toggle; @@ -733,10 +796,16 @@ ed->queueTransfer(); printList(type); enableList(type); +#else + /* call method specific for endpoint */ + td->currBufPtr = buf; + td->size = len; + ret = ed->queueTransfer(); +#endif td_mutex.unlock(); - return USB_TYPE_PROCESSING; + return ret; } @@ -744,12 +813,13 @@ USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_dev_descr) { USB_TYPE t = controlRead( dev, - USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, - GET_DESCRIPTOR, - (DEVICE_DESCRIPTOR << 8) | (0), - 0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf)); - if (len_dev_descr) + USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, + GET_DESCRIPTOR, + (DEVICE_DESCRIPTOR << 8) | (0), + 0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf)); + if (len_dev_descr) { *len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf); + } return t; } @@ -773,8 +843,9 @@ total_conf_descr_length = buf[2] | (buf[3] << 8); total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length); - if (len_conf_descr) + if (len_conf_descr) { *len_conf_descr = total_conf_descr_length; + } USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]); @@ -786,7 +857,8 @@ } -USB_TYPE USBHost::setAddress(USBDeviceConnected * dev, uint8_t address) { +USB_TYPE USBHost::setAddress(USBDeviceConnected * dev, uint8_t address) +{ return controlWrite( dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_ADDRESS, @@ -804,14 +876,17 @@ 0, NULL, 0); } -uint8_t USBHost::numberDriverAttached(USBDeviceConnected * dev) { +uint8_t USBHost::numberDriverAttached(USBDeviceConnected * dev) +{ int index = findDevice(dev); uint8_t cnt = 0; - if (index == -1) + if (index == -1) { return 0; + } for (uint8_t i = 0; i < MAX_INTF; i++) { - if (deviceAttachedDriver[index][i]) + if (deviceAttachedDriver[index][i]) { cnt++; + } } return cnt; } @@ -822,76 +897,76 @@ uint16_t total_conf_descr_length = 0; USB_TYPE res; - do - { - Lock lock(this); + do { + Lock lock(this); - // don't enumerate a device which all interfaces are registered to a specific driver - int index = findDevice(dev); + // don't enumerate a device which all interfaces are registered to a specific driver + int index = findDevice(dev); - if (index == -1) { - return USB_TYPE_ERROR; - } + if (index == -1) { + return USB_TYPE_ERROR; + } - uint8_t nb_intf_attached = numberDriverAttached(dev); - USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf()); - USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached); - if ((nb_intf_attached != 0) && (dev->getNbIntf() == nb_intf_attached)) { - USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev); - return USB_TYPE_OK; - } + uint8_t nb_intf_attached = numberDriverAttached(dev); + USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf()); + USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached); + if ((nb_intf_attached != 0) && (dev->getNbIntf() == nb_intf_attached)) { + USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev); + return USB_TYPE_OK; + } + + USB_DBG("Enumerate dev: %p", dev); - USB_DBG("Enumerate dev: %p", dev); - - // third step: get the whole device descriptor to see vid, pid - res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH); + // third step: get the whole device descriptor to see vid, pid + res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH); - if (res != USB_TYPE_OK) { - USB_DBG("GET DEV DESCR FAILED"); - return res; - } + if (res != USB_TYPE_OK) { + USB_DBG("GET DEV DESCR FAILED"); + return res; + } + + dev->setClass(data[4]); + dev->setSubClass(data[5]); + dev->setProtocol(data[6]); + dev->setVid(data[8] | (data[9] << 8)); + dev->setPid(data[10] | (data[11] << 8)); + USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); - dev->setClass(data[4]); - dev->setSubClass(data[5]); - dev->setProtocol(data[6]); - dev->setVid(data[8] | (data[9] << 8)); - dev->setPid(data[10] | (data[11] << 8)); - USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); + pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); - pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); + res = getConfigurationDescriptor(dev, data, sizeof(data), &total_conf_descr_length); + if (res != USB_TYPE_OK) { + return res; + } - res = getConfigurationDescriptor(dev, data, sizeof(data), &total_conf_descr_length); - if (res != USB_TYPE_OK) { - return res; - } +#if (DEBUG > 3) + USB_DBG("CONFIGURATION DESCRIPTOR:\r\n"); + for (int i = 0; i < total_conf_descr_length; i++) { + printf("%02X ", data[i]); + } + printf("\r\n\r\n"); +#endif - #if (DEBUG > 3) - USB_DBG("CONFIGURATION DESCRIPTOR:\r\n"); - for (int i = 0; i < total_conf_descr_length; i++) - printf("%02X ", data[i]); - printf("\r\n\r\n"); - #endif + // Parse the configuration descriptor + parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); - // Parse the configuration descriptor - parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); + // only set configuration if not enumerated before + if (!dev->isEnumerated()) { - // only set configuration if not enumerated before - if (!dev->isEnumerated()) { - - USB_DBG("Set configuration 1 on dev: %p", dev); - // sixth step: set configuration (only 1 supported) - res = setConfiguration(dev, 1); + USB_DBG("Set configuration 1 on dev: %p", dev); + // sixth step: set configuration (only 1 supported) + res = setConfiguration(dev, 1); - if (res != USB_TYPE_OK) { - USB_DBG("SET CONF FAILED"); - return res; - } - } + if (res != USB_TYPE_OK) { + USB_DBG("SET CONF FAILED"); + return res; + } + } - dev->setEnumerated(); + dev->setEnumerated(); - // Now the device is enumerated! - USB_DBG("dev %p is enumerated\r\n", dev); + // Now the device is enumerated! + USB_DBG("dev %p is enumerated\r\n", dev); } while(0); @@ -990,7 +1065,8 @@ return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, false); } -USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) { +USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) +{ #if DEBUG_TRANSFER const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS"); @@ -1030,16 +1106,28 @@ #if DEBUG_TRANSFER if (write) { USB_DBG_TRANSFER("%s WRITE buffer", type_str); - for (int i = 0; i < ep->getLengthTransferred(); i++) + for (int i = 0; i < ep->getLengthTransferred(); i++) { printf("%02X ", buf[i]); + } printf("\r\n\r\n"); } #endif - addTransfer(ep, buf, len); + res = addTransfer(ep, buf, len); - if (blocking) { - + if ((blocking)&& (res == USB_TYPE_PROCESSING)) { +#ifdef USBHOST_OTHER + osEvent event = ep->ep_queue.get(TD_TIMEOUT); + if (event.status == osEventTimeout) { + /* control endpoint is confusing for merge on b */ + disableList(CONTROL_ENDPOINT); + ep->setState(USB_TYPE_ERROR); + ep->ep_queue.get(0); + ep->unqueueTransfer(ep->getProcessedTD()); + enableList(CONTROL_ENDPOINT); + } +#else ep->ep_queue.get(); +#endif res = ep->getState(); USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str, ep->getStateString(), ep); @@ -1051,16 +1139,18 @@ return USB_TYPE_OK; } - return USB_TYPE_PROCESSING; + return res; } -USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { +USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) +{ return controlTransfer(dev, requestType, request, value, index, buf, len, false); } -USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { +USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) +{ return controlTransfer(dev, requestType, request, value, index, buf, len, true); } @@ -1086,15 +1176,30 @@ #if DEBUG_TRANSFER USB_DBG_TRANSFER("SETUP PACKET: "); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { printf("%01X ", setupPacket[i]); + } printf("\r\n"); #endif control->setNextToken(TD_SETUP); - addTransfer(control, (uint8_t*)setupPacket, 8); + res = addTransfer(control, (uint8_t*)setupPacket, 8); - control->ep_queue.get(); + if (res == USB_TYPE_PROCESSING) +#ifdef USBHOST_OTHER + { + osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); + if (event.status == osEventTimeout) { + disableList(CONTROL_ENDPOINT); + control->setState(USB_TYPE_ERROR); + control->ep_queue.get(0); + control->unqueueTransfer(control->getProcessedTD()); + enableList(CONTROL_ENDPOINT); + } + } +#else + control->ep_queue.get(); +#endif res = control->getState(); USB_DBG_TRANSFER("CONTROL setup stage %s", control->getStateString()); @@ -1106,22 +1211,38 @@ if (length_transfer) { token = (write) ? TD_OUT : TD_IN; control->setNextToken(token); - addTransfer(control, (uint8_t *)buf, length_transfer); + res = addTransfer(control, (uint8_t *)buf, length_transfer); - control->ep_queue.get(); + if (res == USB_TYPE_PROCESSING) +#ifdef USBHOST_OTHER + { + osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); + if (event.status == osEventTimeout) { + disableList(CONTROL_ENDPOINT); + control->setState(USB_TYPE_ERROR); + control->ep_queue.get(0); + control->unqueueTransfer(control->getProcessedTD()); + enableList(CONTROL_ENDPOINT); + } + } +#else + control->ep_queue.get(); +#endif res = control->getState(); #if DEBUG_TRANSFER USB_DBG_TRANSFER("CONTROL %s stage %s", (write) ? "WRITE" : "READ", control->getStateString()); if (write) { USB_DBG_TRANSFER("CONTROL WRITE buffer"); - for (int i = 0; i < control->getLengthTransferred(); i++) + for (int i = 0; i < control->getLengthTransferred(); i++) { printf("%02X ", buf[i]); + } printf("\r\n\r\n"); } else { USB_DBG_TRANSFER("CONTROL READ SUCCESS [%d bytes transferred]", control->getLengthTransferred()); - for (int i = 0; i < control->getLengthTransferred(); i++) + for (int i = 0; i < control->getLengthTransferred(); i++) { printf("%02X ", buf[i]); + } printf("\r\n\r\n"); } #endif @@ -1133,15 +1254,29 @@ token = (write) ? TD_IN : TD_OUT; control->setNextToken(token); - addTransfer(control, NULL, 0); - - control->ep_queue.get(); + res = addTransfer(control, NULL, 0); + if (res == USB_TYPE_PROCESSING) +#ifdef USBHOST_OTHER + { + osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); + if (event.status == osEventTimeout) { + disableList(CONTROL_ENDPOINT); + control->setState(USB_TYPE_ERROR); + control->ep_queue.get(0); + control->unqueueTransfer(control->getProcessedTD()); + enableList(CONTROL_ENDPOINT); + } + } +#else + control->ep_queue.get(); +#endif res = control->getState(); USB_DBG_TRANSFER("CONTROL ack stage %s", control->getStateString()); - if (res != USB_TYPE_IDLE) + if (res != USB_TYPE_IDLE) { return res; + } return USB_TYPE_OK; }
--- a/USBHost/USBHost.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBHost.h Thu Jul 20 10:13:56 2017 +0100 @@ -16,7 +16,9 @@ #ifndef USBHOST_H #define USBHOST_H - +#ifdef TARGET_STM +#include "mbed.h" +#endif #include "USBHALHost.h" #include "USBDeviceConnected.h" #include "IUSBEnumerator.h" @@ -278,7 +280,6 @@ Thread usbThread; void usb_process(); - static void usb_process_static(void const * arg); Mail<message_t, 10> mail_usb_event; Mutex usb_mutex; Mutex td_mutex;
--- a/USBHost/USBHostConf.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBHostConf.h Thu Jul 20 10:13:56 2017 +0100 @@ -16,8 +16,71 @@ #ifndef USBHOST_CONF_H #define USBHOST_CONF_H +#if defined(TARGET_STM) +/* +* Maximum number of devices that can be connected +* to the usb host +*/ +/* hub + 2 devices */ +#define MAX_DEVICE_CONNECTED 5 /* +* Maximum of Hub connected to the usb host +*/ +#define MAX_HUB_NB 3 + +/* +* Maximum number of ports on a USB hub +*/ +#define MAX_HUB_PORT 4 + +/* +* Enable USBHostMSD +*/ +#define USBHOST_MSD 1 + +/* +* Enable USBHostKeyboard +*/ +#define USBHOST_KEYBOARD 1 + +/* +* Enable USBHostMouse +*/ +#define USBHOST_MOUSE 1 + +/* +* Enable USBHostSerial or USBHostMultiSerial (if set > 1) +*/ +#define USBHOST_SERIAL 1 + +/* +* Enable USB3Gmodule +*/ +#define USBHOST_3GMODULE 1 + +/* +* Enable USB MIDI +*/ +#define USBHOST_MIDI 1 + +/* +* Maximum number of interfaces of a usb device +*/ +#define MAX_INTF 2 + +/* +* Maximum number of endpoints on each interface +*/ +#define MAX_ENDPOINT_PER_INTERFACE 2 + +/* +* Maximum number of endpoint descriptors that can be allocated +*/ +#define MAX_ENDPOINT 11 /* USB FS 11 channel */ + +#else +/* * Maximum number of devices that can be connected * to the usb host */ @@ -77,7 +140,7 @@ * Maximum number of endpoint descriptors that can be allocated */ #define MAX_ENDPOINT (MAX_DEVICE_CONNECTED * MAX_INTF * MAX_ENDPOINT_PER_INTERFACE) - +#endif /* * Maximum number of transfer descriptors that can be allocated */ @@ -86,6 +149,6 @@ /* * usb_thread stack size */ -#define USB_THREAD_STACK (256*4 + MAX_HUB_NB*256*4) +#define USB_THREAD_STACK (256*4 + 2*256*4) #endif
--- a/USBHost/USBHostTypes.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHost/USBHostTypes.h Thu Jul 20 10:13:56 2017 +0100 @@ -18,7 +18,7 @@ #define USB_INC_H #include "mbed.h" -#include "toolchain.h" +#include "mbed_toolchain.h" enum USB_TYPE { USB_TYPE_OK = 0, @@ -67,12 +67,16 @@ #define HUB_CLASS 0x09 #define SERIAL_CLASS 0x0A +#if !defined(USBHOST_OTHER) // ------------------ HcControl Register --------------------- #define OR_CONTROL_PLE 0x00000004 #define OR_CONTROL_CLE 0x00000010 #define OR_CONTROL_BLE 0x00000020 #define OR_CONTROL_HCFS 0x000000C0 +#define OR_CONTROL_HC_RSET 0x00000000 +#define OR_CONTROL_HC_RES 0x00000040 #define OR_CONTROL_HC_OPER 0x00000080 +#define OR_CONTROL_HC_SUSP 0x000000C0 // ----------------- HcCommandStatus Register ----------------- #define OR_CMD_STATUS_HCR 0x00000001 #define OR_CMD_STATUS_CLF 0x00000002 @@ -94,6 +98,8 @@ #define OR_RH_PORT_CSC 0x00010000 #define OR_RH_PORT_PRSC 0x00100000 #define OR_RH_PORT_LSDA 0x00000200 +#define OR_RH_PORT_PESC 0x00020000 +#define OR_RH_PORT_OCIC 0x00080000 #define FI 0x2EDF // 12000 bits per frame (-1) #define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI) @@ -109,6 +115,15 @@ #define TD_TOGGLE_1 (uint32_t)(0x03000000) // Toggle 1 #define TD_CC (uint32_t)(0xF0000000) // Completion Code +#else + +#define TD_TIMEOUT_CTRL 100 +#define TD_TIMEOUT 2000 +#define TD_SETUP (uint32_t)(0) // Direction of Setup Packet +#define TD_IN (uint32_t)(0x00100000) // Direction In +#define TD_OUT (uint32_t)(0x00080000) // Direction Out + +#endif #define DEVICE_DESCRIPTOR (1) #define CONFIGURATION_DESCRIPTOR (2) #define INTERFACE_DESCRIPTOR (4) @@ -136,6 +151,29 @@ #define CONFIGURATION_DESCRIPTOR_LENGTH 0x09 // ------------ HostController Transfer Descriptor ------------ +#if defined(USBHOST_OTHER) + +typedef struct hcTd { + __IO uint32_t state; + __IO uint8_t * currBufPtr; // Physical address of current buffer pointer + __IO hcTd * nextTD; // Physical pointer to next Transfer Descriptor + __IO uint32_t size; // size of buffer + void * ep; // ep address where a td is linked in + __IO uint32_t retry; + __IO uint32_t setup; +} PACKED HCTD; +// ----------- HostController EndPoint Descriptor ------------- +typedef struct hcEd { + uint8_t ch_num; + void *hhcd; +} PACKED HCED; +// ----------- Host Controller Communication Area ------------ +#define HCCA void + + +#else +// -------------OHCI register -------------------------------- +// ------------ HostController Transfer Descriptor ------------ typedef struct hcTd { __IO uint32_t control; // Transfer descriptor control __IO uint8_t * currBufPtr; // Physical address of current buffer pointer @@ -144,7 +182,6 @@ void * ep; // ep address where a td is linked in uint32_t dummy[3]; // padding } PACKED HCTD; - // ----------- HostController EndPoint Descriptor ------------- typedef struct hcEd { __IO uint32_t control; // Endpoint descriptor control @@ -152,8 +189,6 @@ __IO HCTD * headTD; // Physcial address of head in Transfer descriptor list __IO hcEd * nextED; // Physical address of next Endpoint descriptor } PACKED HCED; - - // ----------- Host Controller Communication Area ------------ typedef struct hcca { __IO uint32_t IntTable[32]; // Interrupt Table @@ -162,6 +197,7 @@ volatile uint8_t Reserved[116]; // Reserved for future use volatile uint8_t Unknown[4]; // Unused } PACKED HCCA; +#endif typedef struct { uint8_t bLength;
--- a/USBHostHID/USBHostKeyboard.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHID/USBHostKeyboard.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -19,71 +19,81 @@ #if USBHOST_KEYBOARD static uint8_t keymap[4][0x39] = { - { 0, 0, 0, 0, 'a', 'b' /*0x05*/, - 'c', 'd', 'e', 'f', 'g' /*0x0a*/, - 'h', 'i', 'j', 'k', 'l'/*0x0f*/, - 'm', 'n', 'o', 'p', 'q'/*0x14*/, - 'r', 's', 't', 'u', 'v'/*0x19*/, - 'w', 'x', 'y', 'z', '1'/*0x1E*/, - '2', '3', '4', '5', '6'/*0x23*/, - '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/ - 0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/ - '=', '[', ']', '\\', '#', /*0x32*/ - ';', '\'', 0, ',', '.', /*0x37*/ - '/'}, + { + 0, 0, 0, 0, 'a', 'b' /*0x05*/, + 'c', 'd', 'e', 'f', 'g' /*0x0a*/, + 'h', 'i', 'j', 'k', 'l'/*0x0f*/, + 'm', 'n', 'o', 'p', 'q'/*0x14*/, + 'r', 's', 't', 'u', 'v'/*0x19*/, + 'w', 'x', 'y', 'z', '1'/*0x1E*/, + '2', '3', '4', '5', '6'/*0x23*/, + '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/ + 0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/ + '=', '[', ']', '\\', '#', /*0x32*/ + ';', '\'', 0, ',', '.', /*0x37*/ + '/' + }, /* CTRL MODIFIER */ - { 0, 0, 0, 0, 0, 0 /*0x05*/, - 0, 0, 0, 0, 0 /*0x0a*/, - 0, 0, 0, 0, 0/*0x0f*/, - 0, 0, 0, 0, 0/*0x14*/, - 0, 0, 0, 0, 0/*0x19*/, - 0, 0, 0, 0, 0/*0x1E*/, - 0, 0, 0, 0, 0/*0x23*/, - 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - 0, 0, 0, 0, 0, /*0x32*/ - 0, 0, 0, 0, 0, /*0x37*/ - 0}, + { + 0, 0, 0, 0, 0, 0 /*0x05*/, + 0, 0, 0, 0, 0 /*0x0a*/, + 0, 0, 0, 0, 0/*0x0f*/, + 0, 0, 0, 0, 0/*0x14*/, + 0, 0, 0, 0, 0/*0x19*/, + 0, 0, 0, 0, 0/*0x1E*/, + 0, 0, 0, 0, 0/*0x23*/, + 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + 0, 0, 0, 0, 0, /*0x32*/ + 0, 0, 0, 0, 0, /*0x37*/ + 0 + }, /* SHIFT MODIFIER */ - { 0, 0, 0, 0, 'A', 'B' /*0x05*/, - 'C', 'D', 'E', 'F', 'G' /*0x0a*/, - 'H', 'I', 'J', 'K', 'L'/*0x0f*/, - 'M', 'N', 'O', 'P', 'Q'/*0x14*/, - 'R', 'S', 'T', 'U', 'V'/*0x19*/, - 'W', 'X', 'Y', 'Z', '!'/*0x1E*/, - '@', '#', '$', '%', '^'/*0x23*/, - '&', '*', '(', ')', 0, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - '+', '{', '}', '|', '~', /*0x32*/ - ':', '"', 0, '<', '>', /*0x37*/ - '?'}, + { + 0, 0, 0, 0, 'A', 'B' /*0x05*/, + 'C', 'D', 'E', 'F', 'G' /*0x0a*/, + 'H', 'I', 'J', 'K', 'L'/*0x0f*/, + 'M', 'N', 'O', 'P', 'Q'/*0x14*/, + 'R', 'S', 'T', 'U', 'V'/*0x19*/, + 'W', 'X', 'Y', 'Z', '!'/*0x1E*/, + '@', '#', '$', '%', '^'/*0x23*/, + '&', '*', '(', ')', 0, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + '+', '{', '}', '|', '~', /*0x32*/ + ':', '"', 0, '<', '>', /*0x37*/ + '?' + }, /* ALT MODIFIER */ - { 0, 0, 0, 0, 0, 0 /*0x05*/, - 0, 0, 0, 0, 0 /*0x0a*/, - 0, 0, 0, 0, 0/*0x0f*/, - 0, 0, 0, 0, 0/*0x14*/, - 0, 0, 0, 0, 0/*0x19*/, - 0, 0, 0, 0, 0/*0x1E*/, - 0, 0, 0, 0, 0/*0x23*/, - 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ - 0, 0, 0, 0, 0, /*0x2d*/ - 0, 0, 0, 0, 0, /*0x32*/ - 0, 0, 0, 0, 0, /*0x37*/ - 0} + { + 0, 0, 0, 0, 0, 0 /*0x05*/, + 0, 0, 0, 0, 0 /*0x0a*/, + 0, 0, 0, 0, 0/*0x0f*/, + 0, 0, 0, 0, 0/*0x14*/, + 0, 0, 0, 0, 0/*0x19*/, + 0, 0, 0, 0, 0/*0x1E*/, + 0, 0, 0, 0, 0/*0x23*/, + 0, 0, 0, 0, 0 /*enter*/, /*0x28*/ + 0, 0, 0, 0, 0, /*0x2d*/ + 0, 0, 0, 0, 0, /*0x32*/ + 0, 0, 0, 0, 0, /*0x37*/ + 0 + } }; -USBHostKeyboard::USBHostKeyboard() { +USBHostKeyboard::USBHostKeyboard() +{ host = USBHost::getHostInst(); init(); } -void USBHostKeyboard::init() { +void USBHostKeyboard::init() +{ dev = NULL; int_in = NULL; report_id = 0; @@ -94,12 +104,14 @@ keyboard_device_found = false; } -bool USBHostKeyboard::connected() { +bool USBHostKeyboard::connected() +{ return dev_connected; } -bool USBHostKeyboard::connect() { +bool USBHostKeyboard::connect() +{ if (dev_connected) { return true; @@ -108,20 +120,29 @@ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { if ((dev = host->getDevice(i)) != NULL) { - if (host->enumerate(dev, this)) + if (host->enumerate(dev, this)) { break; + } if (keyboard_device_found) { - int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN); + { + /* As this is done in a specific thread + * this lock is taken to avoid to process the device + * disconnect in usb process during the device registering */ + USBHost::Lock Lock(host); - if (!int_in) - break; + int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN); - USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf); - dev->setName("Keyboard", keyboard_intf); - host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init); + if (!int_in) { + break; + } - int_in->attach(this, &USBHostKeyboard::rxHandler); + USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf); + dev->setName("Keyboard", keyboard_intf); + host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init); + + int_in->attach(this, &USBHostKeyboard::rxHandler); + } host->interruptRead(dev, int_in, report, int_in->getSize(), false); dev_connected = true; @@ -133,7 +154,8 @@ return false; } -void USBHostKeyboard::rxHandler() { +void USBHostKeyboard::rxHandler() +{ int len = int_in->getLengthTransferred(); int index = (len == 9) ? 1 : 0; int len_listen = int_in->getSize(); @@ -149,8 +171,9 @@ (*onKeyCode)(report[index + 2], modifier); } } - if (dev && int_in) + if (dev && int_in) { host->interruptRead(dev, int_in, report, len_listen, false); + } } /*virtual*/ void USBHostKeyboard::setVidPid(uint16_t vid, uint16_t pid) @@ -161,9 +184,9 @@ /*virtual*/ bool USBHostKeyboard::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed { if ((keyboard_intf == -1) && - (intf_class == HID_CLASS) && - (intf_subclass == 0x01) && - (intf_protocol == 0x01)) { + (intf_class == HID_CLASS) && + (intf_subclass == 0x01) && + (intf_protocol == 0x01)) { keyboard_intf = intf_nb; return true; }
--- a/USBHostHID/USBHostKeyboard.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHID/USBHostKeyboard.h Thu Jul 20 10:13:56 2017 +0100 @@ -26,7 +26,8 @@ /** * A class to communicate a USB keyboard */ -class USBHostKeyboard : public IUSBEnumerator { +class USBHostKeyboard : public IUSBEnumerator +{ public: /** @@ -53,7 +54,8 @@ * * @param ptr function pointer */ - inline void attach(void (*ptr)(uint8_t key)) { + inline void attach(void (*ptr)(uint8_t key)) + { if (ptr != NULL) { onKey = ptr; } @@ -64,7 +66,8 @@ * * @param ptr function pointer */ - inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) { + inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) + { if (ptr != NULL) { onKeyCode = ptr; }
--- a/USBHostHID/USBHostMouse.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHID/USBHostMouse.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -18,12 +18,14 @@ #if USBHOST_MOUSE -USBHostMouse::USBHostMouse() { +USBHostMouse::USBHostMouse() +{ host = USBHost::getHostInst(); init(); } -void USBHostMouse::init() { +void USBHostMouse::init() +{ dev = NULL; int_in = NULL; onUpdate = NULL; @@ -42,11 +44,13 @@ z = 0; } -bool USBHostMouse::connected() { +bool USBHostMouse::connected() +{ return dev_connected; } -bool USBHostMouse::connect() { +bool USBHostMouse::connect() +{ int len_listen; if (dev_connected) { @@ -56,27 +60,38 @@ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { if ((dev = host->getDevice(i)) != NULL) { - if(host->enumerate(dev, this)) + if(host->enumerate(dev, this)) { break; - + } if (mouse_device_found) { - - int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); - if (!int_in) - break; + { + /* As this is done in a specific thread + * this lock is taken to avoid to process the device + * disconnect in usb process during the device registering */ + USBHost::Lock Lock(host); + int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); + if (!int_in) { + break; + } - USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf); - dev->setName("Mouse", mouse_intf); - host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); + USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf); + dev->setName("Mouse", mouse_intf); + host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); - int_in->attach(this, &USBHostMouse::rxHandler); - len_listen = int_in->getSize(); - if (len_listen > sizeof(report)) { - len_listen = sizeof(report); + int_in->attach(this, &USBHostMouse::rxHandler); + len_listen = int_in->getSize(); + if (len_listen > sizeof(report)) { + len_listen = sizeof(report); + } } - host->interruptRead(dev, int_in, report, len_listen, false); - - dev_connected = true; + int ret=host->interruptRead(dev, int_in, report, len_listen, false); + MBED_ASSERT((ret==USB_TYPE_OK) || (ret ==USB_TYPE_PROCESSING) || (ret == USB_TYPE_FREE)); + if ((ret==USB_TYPE_OK) || (ret ==USB_TYPE_PROCESSING)) { + dev_connected = true; + } + if (ret == USB_TYPE_FREE) { + dev_connected = false; + } return true; } } @@ -85,41 +100,47 @@ return false; } -void USBHostMouse::rxHandler() { - int len_listen = int_in->getSize(); +void USBHostMouse::rxHandler() +{ + int len_listen = int_in->getLengthTransferred(); + if (len_listen !=0) { - if (onUpdate) { - (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]); - } + if (onUpdate) { + (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]); + } + + if (onButtonUpdate && (buttons != (report[0] & 0x07))) { + (*onButtonUpdate)(report[0] & 0x07); + } - if (onButtonUpdate && (buttons != (report[0] & 0x07))) { - (*onButtonUpdate)(report[0] & 0x07); - } + if (onXUpdate && (x != report[1])) { + (*onXUpdate)(report[1]); + } + + if (onYUpdate && (y != report[2])) { + (*onYUpdate)(report[2]); + } - if (onXUpdate && (x != report[1])) { - (*onXUpdate)(report[1]); + if (onZUpdate && (z != report[3])) { + (*onZUpdate)(report[3]); + } + + // update mouse state + buttons = report[0] & 0x07; + x = report[1]; + y = report[2]; + z = report[3]; } - - if (onYUpdate && (y != report[2])) { - (*onYUpdate)(report[2]); - } - - if (onZUpdate && (z != report[3])) { - (*onZUpdate)(report[3]); - } - - // update mouse state - buttons = report[0] & 0x07; - x = report[1]; - y = report[2]; - z = report[3]; + /* set again the maximum value */ + len_listen = int_in->getSize(); if (len_listen > sizeof(report)) { len_listen = sizeof(report); } - if (dev) + if (dev) { host->interruptRead(dev, int_in, report, len_listen, false); + } } /*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid) @@ -130,9 +151,9 @@ /*virtual*/ bool USBHostMouse::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed { if ((mouse_intf == -1) && - (intf_class == HID_CLASS) && - (intf_subclass == 0x01) && - (intf_protocol == 0x02)) { + (intf_class == HID_CLASS) && + (intf_subclass == 0x01) && + (intf_protocol == 0x02)) { mouse_intf = intf_nb; return true; }
--- a/USBHostHID/USBHostMouse.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHID/USBHostMouse.h Thu Jul 20 10:13:56 2017 +0100 @@ -26,7 +26,8 @@ /** * A class to communicate a USB mouse */ -class USBHostMouse : public IUSBEnumerator { +class USBHostMouse : public IUSBEnumerator +{ public: /** @@ -53,7 +54,8 @@ * * @param ptr function pointer */ - inline void attachEvent(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) { + inline void attachEvent(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) + { if (ptr != NULL) { onUpdate = ptr; } @@ -64,7 +66,8 @@ * * @param ptr function pointer */ - inline void attachButtonEvent(void (*ptr)(uint8_t buttons)) { + inline void attachButtonEvent(void (*ptr)(uint8_t buttons)) + { if (ptr != NULL) { onButtonUpdate = ptr; } @@ -75,7 +78,8 @@ * * @param ptr function pointer */ - inline void attachXEvent(void (*ptr)(int8_t x)) { + inline void attachXEvent(void (*ptr)(int8_t x)) + { if (ptr != NULL) { onXUpdate = ptr; } @@ -86,7 +90,8 @@ * * @param ptr function pointer */ - inline void attachYEvent(void (*ptr)(int8_t y)) { + inline void attachYEvent(void (*ptr)(int8_t y)) + { if (ptr != NULL) { onYUpdate = ptr; } @@ -97,7 +102,8 @@ * * @param ptr function pointer */ - inline void attachZEvent(void (*ptr)(int8_t z)) { + inline void attachZEvent(void (*ptr)(int8_t z)) + { if (ptr != NULL) { onZUpdate = ptr; } @@ -113,8 +119,7 @@ USBHost * host; USBDeviceConnected * dev; USBEndpoint * int_in; - uint8_t report[4]; - + uint8_t report[64]; bool dev_connected; bool mouse_device_found; int mouse_intf;
--- a/USBHostHub/USBHostHub.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHub/USBHostHub.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -50,12 +50,14 @@ #define C_PORT_OVER_CURRENT (1 << 19) #define C_PORT_RESET (1 << 20) -USBHostHub::USBHostHub() { +USBHostHub::USBHostHub() +{ host = NULL; init(); } -void USBHostHub::init() { +void USBHostHub::init() +{ dev_connected = false; dev = NULL; int_in = NULL; @@ -70,7 +72,8 @@ } } -void USBHostHub::setHost(USBHost * host_) { +void USBHostHub::setHost(USBHost * host_) +{ host = host_; } @@ -129,7 +132,8 @@ return false; } -void USBHostHub::disconnect() { +void USBHostHub::disconnect() +{ init(); } @@ -141,9 +145,9 @@ /*virtual*/ bool USBHostHub::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed { if ((hub_intf == -1) && - (intf_class == HUB_CLASS) && - (intf_subclass == 0) && - (intf_protocol == 0)) { + (intf_class == HUB_CLASS) && + (intf_subclass == 0) && + (intf_protocol == 0)) { hub_intf = intf_nb; return true; } @@ -161,15 +165,18 @@ return false; } -void USBHostHub::deviceConnected(USBDeviceConnected * dev) { +void USBHostHub::deviceConnected(USBDeviceConnected * dev) +{ device_children[dev->getPort() - 1] = dev; } -void USBHostHub::deviceDisconnected(USBDeviceConnected * dev) { +void USBHostHub::deviceDisconnected(USBDeviceConnected * dev) +{ device_children[dev->getPort() - 1] = NULL; } -void USBHostHub::hubDisconnected() { +void USBHostHub::hubDisconnected() +{ for (uint8_t i = 0; i < MAX_HUB_PORT; i++) { if (device_children[i] != NULL) { host->freeDevice(device_children[i]); @@ -177,10 +184,11 @@ } } -void USBHostHub::rxHandler() { +void USBHostHub::rxHandler() +{ uint32_t status; if (int_in) { - if (int_in->getState() == USB_TYPE_IDLE) { + if ((int_in->getLengthTransferred())&&(int_in->getState() == USB_TYPE_IDLE)) { for (int port = 1; port <= nb_port; port++) { status = getPortStatus(port); USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status); @@ -217,7 +225,8 @@ } } -void USBHostHub::portReset(uint8_t port) { +void USBHostHub::portReset(uint8_t port) +{ // reset port uint32_t status; USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this) @@ -227,8 +236,13 @@ #endif while(1) { status = getPortStatus(port); - if (status & (PORT_ENABLE | PORT_RESET)) + /* disconnection since reset request */ + if (!(status & PORT_CONNECTION)) { break; + } + if (status & (PORT_ENABLE | PORT_RESET)) { + break; + } if (status & PORT_OVER_CURRENT) { USB_ERR("OVER CURRENT DETECTED\r\n"); clearPortFeature(PORT_OVER_CURRENT, port); @@ -239,7 +253,8 @@ } } -void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) { +void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) +{ host->controlWrite( dev, USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, SET_FEATURE, @@ -249,7 +264,8 @@ 0); } -void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) { +void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) +{ host->controlWrite( dev, USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT, CLEAR_FEATURE, @@ -259,7 +275,8 @@ 0); } -uint32_t USBHostHub::getPortStatus(uint8_t port) { +uint32_t USBHostHub::getPortStatus(uint8_t port) +{ uint32_t st; host->controlRead( dev, USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
--- a/USBHostHub/USBHostHub.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostHub/USBHostHub.h Thu Jul 20 10:13:56 2017 +0100 @@ -31,7 +31,8 @@ /** * A class to use a USB Hub */ -class USBHostHub : public IUSBEnumerator { +class USBHostHub : public IUSBEnumerator +{ public: /** * Constructor
--- a/USBHostMSD/USBHostMSD.cpp Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostMSD/USBHostMSD.cpp Thu Jul 20 10:13:56 2017 +0100 @@ -72,6 +72,11 @@ break; if (msd_device_found) { + /* As this is done in a specific thread + * this lock is taken to avoid to process a disconnection in + * usb process during the device registering */ + USBHost::Lock Lock(host); + bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); @@ -122,13 +127,15 @@ } -int USBHostMSD::testUnitReady() { +int USBHostMSD::testUnitReady() +{ USB_DBG("Test unit ready"); return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0); } -int USBHostMSD::readCapacity() { +int USBHostMSD::readCapacity() +{ USB_DBG("Read capacity"); uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0}; uint8_t result[8]; @@ -142,7 +149,8 @@ } -int USBHostMSD::SCSIRequestSense() { +int USBHostMSD::SCSIRequestSense() +{ USB_DBG("Request sense"); uint8_t cmd[6] = {0x03,0,0,0,18,0}; uint8_t result[18]; @@ -151,7 +159,8 @@ } -int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) { +int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) +{ USB_DBG("Inquiry"); uint8_t evpd = (page_code == 0) ? 0 : 1; uint8_t cmd[6] = {0x12, uint8_t((lun << 5) | evpd), page_code, 0, 36, 0}; @@ -174,7 +183,8 @@ return status; } -int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) { +int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) +{ // if ep stalled: send clear feature if (res == USB_TYPE_STALL_ERROR) { res = host->controlWrite( dev, @@ -194,7 +204,8 @@ } -int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) { +int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) +{ int res = 0; @@ -277,7 +288,8 @@ } -int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) { +int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) +{ uint8_t cmd[10]; memset(cmd,0,10); cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; @@ -293,7 +305,8 @@ return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock); } -int USBHostMSD::getMaxLun() { +int USBHostMSD::getMaxLun() +{ uint8_t buf[1], res; res = host->controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, 0xfe, 0, msd_intf, buf, 1);
--- a/USBHostSerial/USBHostSerial.h Sun Apr 30 04:17:16 2017 +0000 +++ b/USBHostSerial/USBHostSerial.h Thu Jul 20 10:13:56 2017 +0100 @@ -24,6 +24,7 @@ #include "USBHost.h" #include "Stream.h" #include "MtxCircBuffer.h" +#include "Callback.h" /** * A class to communicate a USB virtual serial port @@ -137,8 +138,8 @@ void rxHandler(); void txHandler(); - FunctionPointer rx; - FunctionPointer tx; + Callback<void()> rx; + Callback<void()> tx; uint8_t serial_intf; };