diff options
Diffstat (limited to 'stmhal/usbhost/Core/Src/usbh_ctlreq.c')
| -rw-r--r-- | stmhal/usbhost/Core/Src/usbh_ctlreq.c | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/stmhal/usbhost/Core/Src/usbh_ctlreq.c b/stmhal/usbhost/Core/Src/usbh_ctlreq.c new file mode 100644 index 000000000..58bc34d64 --- /dev/null +++ b/stmhal/usbhost/Core/Src/usbh_ctlreq.c @@ -0,0 +1,881 @@ +/**
+ ******************************************************************************
+ * @file usbh_ctlreq.c
+ * @author MCD Application Team
+ * @version V3.0.0
+ * @date 18-February-2014
+ * @brief This file implements the control requests for device enumeration
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
+ *
+ * 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.
+ *
+ ******************************************************************************
+ */
+/* Includes ------------------------------------------------------------------*/
+
+#include "usbh_ctlreq.h"
+
+/** @addtogroup USBH_LIB
+* @{
+*/
+
+/** @addtogroup USBH_LIB_CORE
+* @{
+*/
+
+/** @defgroup USBH_CTLREQ
+* @brief This file implements the standard requests for device enumeration
+* @{
+*/
+
+
+/** @defgroup USBH_CTLREQ_Private_Defines
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CTLREQ_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+
+/** @defgroup USBH_CTLREQ_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CTLREQ_Private_Variables
+* @{
+*/
+/**
+* @}
+*/
+
+/** @defgroup USBH_CTLREQ_Private_FunctionPrototypes
+* @{
+*/
+static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost);
+
+static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length);
+
+static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
+ uint8_t *buf,
+ uint16_t length);
+
+
+static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf);
+static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length);
+static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf);
+
+
+/**
+* @}
+*/
+
+
+/** @defgroup USBH_CTLREQ_Private_Functions
+* @{
+*/
+
+
+/**
+ * @brief USBH_Get_DevDesc
+ * Issue Get Device Descriptor command to the device. Once the response
+ * received, it parses the device descriptor and updates the status.
+ * @param phost: Host Handle
+ * @param length: Length of the descriptor
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length)
+{
+ USBH_StatusTypeDef status;
+
+ if((status = USBH_GetDescriptor(phost,
+ USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
+ USB_DESC_DEVICE,
+ phost->device.Data,
+ length)) == USBH_OK)
+ {
+ /* Commands successfully sent and Response Received */
+ USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length);
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_Get_CfgDesc
+ * Issues Configuration Descriptor to the device. Once the response
+ * received, it parses the configuartion descriptor and updates the
+ * status.
+ * @param phost: Host Handle
+ * @param length: Length of the descriptor
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,
+ uint16_t length)
+
+{
+ USBH_StatusTypeDef status;
+ uint8_t *pData;
+#if (USBH_KEEP_CFG_DESCRIPTOR == 1)
+ pData = phost->device.CfgDesc_Raw;
+#else
+ pData = phost->device.Data;
+#endif
+ if((status = USBH_GetDescriptor(phost,
+ USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
+ USB_DESC_CONFIGURATION,
+ pData,
+ length)) == USBH_OK)
+ {
+
+ /* Commands successfully sent and Response Received */
+ USBH_ParseCfgDesc (&phost->device.CfgDesc,
+ pData,
+ length);
+
+ }
+ return status;
+}
+
+
+/**
+ * @brief USBH_Get_StringDesc
+ * Issues string Descriptor command to the device. Once the response
+ * received, it parses the string descriptor and updates the status.
+ * @param phost: Host Handle
+ * @param string_index: String index for the descriptor
+ * @param buff: Buffer address for the descriptor
+ * @param length: Length of the descriptor
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost,
+ uint8_t string_index,
+ uint8_t *buff,
+ uint16_t length)
+{
+ USBH_StatusTypeDef status;
+ if((status = USBH_GetDescriptor(phost,
+ USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
+ USB_DESC_STRING | string_index,
+ phost->device.Data,
+ length)) == USBH_OK)
+ {
+ /* Commands successfully sent and Response Received */
+ USBH_ParseStringDesc(phost->device.Data,buff, length);
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_GetDescriptor
+ * Issues Descriptor command to the device. Once the response received,
+ * it parses the descriptor and updates the status.
+ * @param phost: Host Handle
+ * @param req_type: Descriptor type
+ * @param value_idx: wValue for the GetDescriptr request
+ * @param buff: Buffer to store the descriptor
+ * @param length: Length of the descriptor
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost,
+ uint8_t req_type,
+ uint16_t value_idx,
+ uint8_t* buff,
+ uint16_t length )
+{
+ if(phost->RequestState == CMD_SEND)
+ {
+ phost->Control.setup.b.bmRequestType = USB_D2H | req_type;
+ phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
+ phost->Control.setup.b.wValue.w = value_idx;
+
+ if ((value_idx & 0xff00) == USB_DESC_STRING)
+ {
+ phost->Control.setup.b.wIndex.w = 0x0409;
+ }
+ else
+ {
+ phost->Control.setup.b.wIndex.w = 0;
+ }
+ phost->Control.setup.b.wLength.w = length;
+ }
+ return USBH_CtlReq(phost, buff , length );
+}
+
+/**
+ * @brief USBH_SetAddress
+ * This command sets the address to the connected device
+ * @param phost: Host Handle
+ * @param DeviceAddress: Device address to assign
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost,
+ uint8_t DeviceAddress)
+{
+ if(phost->RequestState == CMD_SEND)
+ {
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \
+ USB_REQ_TYPE_STANDARD;
+
+ phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS;
+
+ phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = 0;
+ }
+ return USBH_CtlReq(phost, 0 , 0 );
+}
+
+/**
+ * @brief USBH_SetCfg
+ * The command sets the configuration value to the connected device
+ * @param phost: Host Handle
+ * @param cfg_idx: Configuration value
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost,
+ uint16_t cfg_idx)
+{
+ if(phost->RequestState == CMD_SEND)
+ {
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\
+ USB_REQ_TYPE_STANDARD;
+ phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
+ phost->Control.setup.b.wValue.w = cfg_idx;
+ phost->Control.setup.b.wIndex.w = 0;
+ phost->Control.setup.b.wLength.w = 0;
+ }
+
+ return USBH_CtlReq(phost, 0 , 0 );
+}
+
+/**
+ * @brief USBH_SetInterface
+ * The command sets the Interface value to the connected device
+ * @param phost: Host Handle
+ * @param altSetting: Interface value
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost,
+ uint8_t ep_num, uint8_t altSetting)
+{
+
+ if(phost->RequestState == CMD_SEND)
+ {
+ phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
+ USB_REQ_TYPE_STANDARD;
+
+ phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE;
+ phost->Control.setup.b.wValue.w = altSetting;
+ phost->Control.setup.b.wIndex.w = ep_num;
+ phost->Control.setup.b.wLength.w = 0;
+ }
+ return USBH_CtlReq(phost, 0 , 0 );
+}
+
+/**
+ * @brief USBH_ClrFeature
+ * This request is used to clear or disable a specific feature.
+ * @param phost: Host Handle
+ * @param ep_num: endpoint number
+ * @param hc_num: Host channel number
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost,
+ uint8_t ep_num)
+{
+ if(phost->RequestState == CMD_SEND)
+ {
+ phost->Control.setup.b.bmRequestType = USB_H2D |
+ USB_REQ_RECIPIENT_ENDPOINT |
+ USB_REQ_TYPE_STANDARD;
+
+ phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
+ phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
+ phost->Control.setup.b.wIndex.w = ep_num;
+ phost->Control.setup.b.wLength.w = 0;
+ }
+ return USBH_CtlReq(phost, 0 , 0 );
+}
+
+/**
+ * @brief USBH_ParseDevDesc
+ * This function Parses the device descriptor
+ * @param dev_desc: device_descriptor destinaton address
+ * @param buf: Buffer where the source descriptor is available
+ * @param length: Length of the descriptor
+ * @retval None
+ */
+static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc,
+ uint8_t *buf,
+ uint16_t length)
+{
+ dev_desc->bLength = *(uint8_t *) (buf + 0);
+ dev_desc->bDescriptorType = *(uint8_t *) (buf + 1);
+ dev_desc->bcdUSB = LE16 (buf + 2);
+ dev_desc->bDeviceClass = *(uint8_t *) (buf + 4);
+ dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5);
+ dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6);
+ dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7);
+
+ if (length > 8)
+ { /* For 1st time after device connection, Host may issue only 8 bytes for
+ Device Descriptor Length */
+ dev_desc->idVendor = LE16 (buf + 8);
+ dev_desc->idProduct = LE16 (buf + 10);
+ dev_desc->bcdDevice = LE16 (buf + 12);
+ dev_desc->iManufacturer = *(uint8_t *) (buf + 14);
+ dev_desc->iProduct = *(uint8_t *) (buf + 15);
+ dev_desc->iSerialNumber = *(uint8_t *) (buf + 16);
+ dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17);
+ }
+}
+
+/**
+ * @brief USBH_ParseCfgDesc
+ * This function Parses the configuration descriptor
+ * @param cfg_desc: Configuration Descriptor address
+ * @param buf: Buffer where the source descriptor is available
+ * @param length: Length of the descriptor
+ * @retval None
+ */
+static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
+ uint8_t *buf,
+ uint16_t length)
+{
+ USBH_InterfaceDescTypeDef *pif ;
+ USBH_EpDescTypeDef *pep;
+ USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf;
+ uint16_t ptr;
+ int8_t if_ix = 0;
+ int8_t ep_ix = 0;
+
+ pdesc = (USBH_DescHeader_t *)buf;
+
+ /* Parse configuration descriptor */
+ cfg_desc->bLength = *(uint8_t *) (buf + 0);
+ cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1);
+ cfg_desc->wTotalLength = LE16 (buf + 2);
+ cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4);
+ cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5);
+ cfg_desc->iConfiguration = *(uint8_t *) (buf + 6);
+ cfg_desc->bmAttributes = *(uint8_t *) (buf + 7);
+ cfg_desc->bMaxPower = *(uint8_t *) (buf + 8);
+
+
+ if (length > USB_CONFIGURATION_DESC_SIZE)
+ {
+ ptr = USB_LEN_CFG_DESC;
+ pif = (USBH_InterfaceDescTypeDef *)0;
+
+
+ while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength))
+ {
+ pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
+ if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE)
+ {
+ pif = &cfg_desc->Itf_Desc[if_ix];
+ USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc);
+
+ ep_ix = 0;
+ pep = (USBH_EpDescTypeDef *)0;
+ while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength))
+ {
+ pdesc = USBH_GetNextDesc((void* )pdesc, &ptr);
+ if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
+ {
+ pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix];
+ USBH_ParseEPDesc (pep, (uint8_t *)pdesc);
+ ep_ix++;
+ }
+ }
+ if_ix++;
+ }
+ }
+ }
+}
+
+
+
+/**
+ * @brief USBH_ParseInterfaceDesc
+ * This function Parses the interface descriptor
+ * @param if_descriptor : Interface descriptor destination
+ * @param buf: Buffer where the descriptor data is available
+ * @retval None
+ */
+static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor,
+ uint8_t *buf)
+{
+ if_descriptor->bLength = *(uint8_t *) (buf + 0);
+ if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
+ if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2);
+ if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3);
+ if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4);
+ if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5);
+ if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6);
+ if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7);
+ if_descriptor->iInterface = *(uint8_t *) (buf + 8);
+}
+
+/**
+ * @brief USBH_ParseEPDesc
+ * This function Parses the endpoint descriptor
+ * @param ep_descriptor: Endpoint descriptor destination address
+ * @param buf: Buffer where the parsed descriptor stored
+ * @retval None
+ */
+static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor,
+ uint8_t *buf)
+{
+
+ ep_descriptor->bLength = *(uint8_t *) (buf + 0);
+ ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
+ ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2);
+ ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3);
+ ep_descriptor->wMaxPacketSize = LE16 (buf + 4);
+ ep_descriptor->bInterval = *(uint8_t *) (buf + 6);
+}
+
+/**
+ * @brief USBH_ParseStringDesc
+ * This function Parses the string descriptor
+ * @param psrc: Source pointer containing the descriptor data
+ * @param pdest: Destination address pointer
+ * @param length: Length of the descriptor
+ * @retval None
+ */
+static void USBH_ParseStringDesc (uint8_t* psrc,
+ uint8_t* pdest,
+ uint16_t length)
+{
+ uint16_t strlength;
+ uint16_t idx;
+
+ /* The UNICODE string descriptor is not NULL-terminated. The string length is
+ computed by substracting two from the value of the first byte of the descriptor.
+ */
+
+ /* Check which is lower size, the Size of string or the length of bytes read
+ from the device */
+
+ if ( psrc[1] == USB_DESC_TYPE_STRING)
+ { /* Make sure the Descriptor is String Type */
+
+ /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
+ strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length);
+ psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */
+
+ for (idx = 0; idx < strlength; idx+=2 )
+ {/* Copy Only the string and ignore the UNICODE ID, hence add the src */
+ *pdest = psrc[idx];
+ pdest++;
+ }
+ *pdest = 0; /* mark end of string */
+ }
+}
+
+/**
+ * @brief USBH_GetNextDesc
+ * This function return the next descriptor header
+ * @param buf: Buffer where the cfg descriptor is available
+ * @param ptr: data popinter inside the cfg descriptor
+ * @retval next header
+ */
+USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr)
+{
+ USBH_DescHeader_t *pnext;
+
+ *ptr += ((USBH_DescHeader_t *)pbuf)->bLength;
+ pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \
+ ((USBH_DescHeader_t *)pbuf)->bLength);
+
+ return(pnext);
+}
+
+
+/**
+ * @brief USBH_CtlReq
+ * USBH_CtlReq sends a control request and provide the status after
+ * completion of the request
+ * @param phost: Host Handle
+ * @param req: Setup Request Structure
+ * @param buff: data buffer address to store the response
+ * @param length: length of the response
+ * @retval USBH Status
+ */
+USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost,
+ uint8_t *buff,
+ uint16_t length)
+{
+ USBH_StatusTypeDef status;
+ status = USBH_BUSY;
+
+ switch (phost->RequestState)
+ {
+ case CMD_SEND:
+ /* Start a SETUP transfer */
+ phost->Control.buff = buff;
+ phost->Control.length = length;
+ phost->Control.state = CTRL_SETUP;
+ phost->RequestState = CMD_WAIT;
+ status = USBH_BUSY;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ break;
+
+ case CMD_WAIT:
+ status = USBH_HandleControl(phost);
+ if (status == USBH_OK)
+ {
+ /* Commands successfully sent and Response Received */
+ phost->RequestState = CMD_SEND;
+ phost->Control.state =CTRL_IDLE;
+ status = USBH_OK;
+ }
+ else if (status == USBH_FAIL)
+ {
+ /* Failure Mode */
+ phost->RequestState = CMD_SEND;
+ status = USBH_FAIL;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief USBH_HandleControl
+ * Handles the USB control transfer state machine
+ * @param phost: Host Handle
+ * @retval USBH Status
+ */
+static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost)
+{
+ uint8_t direction;
+ USBH_StatusTypeDef status = USBH_BUSY;
+ USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
+
+ switch (phost->Control.state)
+ {
+ case CTRL_SETUP:
+ /* send a SETUP packet */
+ USBH_CtlSendSetup (phost,
+ (uint8_t *)phost->Control.setup.d8 ,
+ phost->Control.pipe_out);
+
+ phost->Control.state = CTRL_SETUP_WAIT;
+ break;
+
+ case CTRL_SETUP_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out);
+ /* case SETUP packet sent successfully */
+ if(URB_Status == USBH_URB_DONE)
+ {
+ direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK);
+
+ /* check if there is a data stage */
+ if (phost->Control.setup.b.wLength.w != 0 )
+ {
+ if (direction == USB_D2H)
+ {
+ /* Data Direction is IN */
+ phost->Control.state = CTRL_DATA_IN;
+ }
+ else
+ {
+ /* Data Direction is OUT */
+ phost->Control.state = CTRL_DATA_OUT;
+ }
+ }
+ /* No DATA stage */
+ else
+ {
+ /* If there is No Data Transfer Stage */
+ if (direction == USB_D2H)
+ {
+ /* Data Direction is IN */
+ phost->Control.state = CTRL_STATUS_OUT;
+ }
+ else
+ {
+ /* Data Direction is OUT */
+ phost->Control.state = CTRL_STATUS_IN;
+ }
+ }
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_ERROR)
+ {
+ phost->Control.state = CTRL_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ break;
+
+ case CTRL_DATA_IN:
+ /* Issue an IN token */
+ phost->Control.timer = phost->Timer;
+ USBH_CtlReceiveData(phost,
+ phost->Control.buff,
+ phost->Control.length,
+ phost->Control.pipe_in);
+
+ phost->Control.state = CTRL_DATA_IN_WAIT;
+ break;
+
+ case CTRL_DATA_IN_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
+
+ /* check is DATA packet transfered successfully */
+ if (URB_Status == USBH_URB_DONE)
+ {
+ phost->Control.state = CTRL_STATUS_OUT;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+
+ /* manage error cases*/
+ if (URB_Status == USBH_URB_STALL)
+ {
+ /* In stall case, return to previous machine state*/
+ status = USBH_NOT_SUPPORTED;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if (URB_Status == USBH_URB_ERROR)
+ {
+ /* Device error */
+ phost->Control.state = CTRL_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ break;
+
+ case CTRL_DATA_OUT:
+
+ USBH_CtlSendData (phost,
+ phost->Control.buff,
+ phost->Control.length ,
+ phost->Control.pipe_out,
+ 1);
+ phost->Control.timer = phost->Timer;
+ phost->Control.state = CTRL_DATA_OUT_WAIT;
+ break;
+
+ case CTRL_DATA_OUT_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
+
+ if (URB_Status == USBH_URB_DONE)
+ { /* If the Setup Pkt is sent successful, then change the state */
+ phost->Control.state = CTRL_STATUS_IN;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+
+ /* handle error cases */
+ else if (URB_Status == USBH_URB_STALL)
+ {
+ /* In stall case, return to previous machine state*/
+ phost->Control.state = CTRL_STALLED;
+ status = USBH_NOT_SUPPORTED;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if (URB_Status == USBH_URB_NOTREADY)
+ {
+ /* Nack received from device */
+ phost->Control.state = CTRL_DATA_OUT;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if (URB_Status == USBH_URB_ERROR)
+ {
+ /* device error */
+ phost->Control.state = CTRL_ERROR;
+ status = USBH_FAIL;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ break;
+
+
+ case CTRL_STATUS_IN:
+ /* Send 0 bytes out packet */
+ USBH_CtlReceiveData (phost,
+ 0,
+ 0,
+ phost->Control.pipe_in);
+ phost->Control.timer = phost->Timer;
+ phost->Control.state = CTRL_STATUS_IN_WAIT;
+
+ break;
+
+ case CTRL_STATUS_IN_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
+
+ if ( URB_Status == USBH_URB_DONE)
+ { /* Control transfers completed, Exit the State Machine */
+ phost->Control.state = CTRL_COMPLETE;
+ status = USBH_OK;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+
+ else if (URB_Status == USBH_URB_ERROR)
+ {
+ phost->Control.state = CTRL_ERROR;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ /* Control transfers completed, Exit the State Machine */
+ status = USBH_NOT_SUPPORTED;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ break;
+
+ case CTRL_STATUS_OUT:
+ USBH_CtlSendData (phost,
+ 0,
+ 0,
+ phost->Control.pipe_out,
+ 1);
+ phost->Control.timer = phost->Timer;
+ phost->Control.state = CTRL_STATUS_OUT_WAIT;
+ break;
+
+ case CTRL_STATUS_OUT_WAIT:
+
+ URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
+ if (URB_Status == USBH_URB_DONE)
+ {
+ status = USBH_OK;
+ phost->Control.state = CTRL_COMPLETE;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if (URB_Status == USBH_URB_NOTREADY)
+ {
+ phost->Control.state = CTRL_STATUS_OUT;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ else if (URB_Status == USBH_URB_ERROR)
+ {
+ phost->Control.state = CTRL_ERROR;
+
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
+#endif
+ }
+ break;
+
+ case CTRL_ERROR:
+ /*
+ After a halt condition is encountered or an error is detected by the
+ host, a control endpoint is allowed to recover by accepting the next Setup
+ PID; i.e., recovery actions via some other pipe are not required for control
+ endpoints. For the Default Control Pipe, a device reset will ultimately be
+ required to clear the halt or error condition if the next Setup PID is not
+ accepted.
+ */
+ if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT)
+ {
+ /* try to recover control */
+ USBH_LL_Stop(phost);
+
+ /* Do the transmission again, starting from SETUP Packet */
+ phost->Control.state = CTRL_SETUP;
+ phost->RequestState = CMD_SEND;
+ }
+ else
+ {
+ phost->Control.errorcount = 0;
+ USBH_ErrLog("Control error");
+ status = USBH_FAIL;
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+
+
|
