1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-24 00:35:39 +03:00

Initiate APM32F40X MCU Support in Betaflight (#13709)

* Add APM32F4 driver libraries and USB middleware
* Remove all duplicated APM32 driver files and retaining only the APM32 LIB directory
This commit is contained in:
Morro 2024-06-28 13:03:34 +08:00 committed by GitHub
parent 2ff71b0a1f
commit 14bcc13150
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
258 changed files with 290932 additions and 0 deletions

View file

@ -0,0 +1,200 @@
/*!
* @file usbh_cdc.h
*
* @brief USB CDC core function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_CDC_H_
#define _USBH_CDC_H_
/* Includes */
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_CDC_Class
@{
*/
/** @defgroup USBH_CDC_Macros Macros
@{
*/
#define USBH_CDC_ACM_CODE 0x02
#define USBH_CDC_AT_COMMAND_CODE 0x01
#define USBH_CDC_LINE_CODING_NUM 0x07
/**@} end of group USBH_CDC_Macros*/
/** @defgroup USBH_CDC_Enumerates Enumerates
@{
*/
/**
* @brief USB CDC state table
*/
typedef enum
{
USBH_CDC_INIT = 0,
USBH_CDC_IDLE = 1,
USBH_CDC_SET_LINE_CODING_STATE,
USBH_CDC_GET_LINE_CODING_STATE,
USBH_CDC_SET_CONTROL_LINE_STATE,
USBH_CDC_TRANSFER_DATA_STATE,
USBH_CDC_ERROR_STATE,
} USBH_CDC_STATE_T;
/**
* @brief USB CDC data state table
*/
typedef enum
{
USBH_CDC_DATA_IDLE = 0,
USBH_CDC_DATA_SEND,
USBH_CDC_DATA_SEND_WAIT,
USBH_CDC_DATA_RECEIVE,
USBH_CDC_DATA_RECEIVE_WAIT,
USBH_CDC_DATA_ERROR,
} USBH_CDC_DATA_STATE_T;
/**
* @brief USB CDC device class requests type
*/
typedef enum
{
USBH_CDC_REQ_SEND_ENCAPSULATED_COMMAND = 0,
USBH_CDC_REQ_SET_LINE_CODING = 0x20,
USBH_CDC_REQ_GET_LINE_CODING,
USBH_CDC_REQ_SET_CONTROL_LINE_STATE,
} USBH_CDC_REQ_TYPE_T;
/**@} end of group USBH_CDC_Enumerates*/
/** @defgroup USBH_CDC_Structures Structures
@{
*/
/* Host CDC class state handler function */
typedef USBH_STA_T(*USBH_CDCStateHandler_T)(USBH_INFO_T* usbInfo);
typedef USBH_STA_T(*USBH_CDCDataHandler_T)(USBH_INFO_T* usbInfo);
/**
* @brief CDC line coding structure
*/
typedef union
{
uint8_t data[USBH_CDC_LINE_CODING_NUM];
struct
{
uint32_t dwDTERate;
uint8_t bCharFormat;
uint8_t bParityType;
uint8_t bDataBits;
} DATA_B;
} USBH_CDC_LINE_CODING_T;
/**
* @brief CDC control line state structure
*/
typedef union
{
uint8_t bitmap;
struct
{
uint8_t DTR : 1;
uint8_t RTS : 1;
uint8_t RESERVED : 6;
} DATA_B;
} USBH_CDC_CONTROL_LINE_STATE_T;
/**
* @brief CDC communication data
*/
typedef struct
{
uint8_t notifyChNum;
uint8_t notifyEpAddr;
uint16_t notifyEpsize;
uint8_t notifyBuffer[8];
} USBH_CDC_COMMUNICATION_T;
/**
* @brief CDC transfer data
*/
typedef struct
{
uint32_t txdLength;
uint32_t rxdLength;
uint8_t* txBuffer;
uint8_t* rxBuffer;
uint8_t inChNum;
uint8_t outChNum;
uint8_t inEpAddr;
uint8_t outEpAddr;
uint16_t inEpsize;
uint16_t outEpsize;
uint8_t dataBuffer[8];
} USBH_CDC_XFER_T;
/**
* @brief CDC information management
*/
typedef struct
{
USBH_CDC_STATE_T state;
USBH_CDC_DATA_STATE_T dataXferState;
USBH_CDC_XFER_T dataXfer;
USBH_CDC_LINE_CODING_T userLineCoding;
USBH_CDC_LINE_CODING_T* lineCoding;
USBH_CDC_CONTROL_LINE_STATE_T* controlLine;
USBH_CDC_COMMUNICATION_T comm;
uint32_t timer;
} USBH_CDC_INFO_T;
extern USBH_CLASS_T USBH_CDC_CLASS;
/**@} end of group USBH_CDC_Structures*/
/** @defgroup USBH_CDC_Functions Functions
@{
*/
USBH_CDC_DATA_STATE_T USBH_CDC_ReadDataStatus(USBH_INFO_T* usbInfo);
uint16_t USBH_CDC_ReadRevDataSize(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_CDC_SendData(USBH_INFO_T* usbInfo, uint8_t* buffer, uint32_t length);
USBH_STA_T USBH_CDC_ReceiveData(USBH_INFO_T* usbInfo, uint8_t* buffer, uint32_t length);
void USBH_CDC_LineCodingIsChangeCallback(USBH_INFO_T* usbInfo);
void USBH_CDC_XferEndCallback(USBH_INFO_T* usbInfo);
void USBH_CDC_RevEndCallback(USBH_INFO_T* usbInfo);
/**@} end of group USBH_CDC_Functions */
/**@} end of group USBH_CDC_Class */
/**@} end of group APM32_USB_Library */
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,180 @@
/*!
* @file usbh_hid.h
*
* @brief USB HID core function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_HID_H_
#define _USBH_HID_H_
/* Includes */
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Macros Macros
@{
*/
#define USBH_HID_CLASS_CODE 0x03
#define USBH_HID_BOOT_CODE 0x01
#define USBH_HID_MOUSE_BOOT_CODE 0x02
#define USBH_HID_KEYBOARD_BOOT_CODE 0x01
#define USBH_HID_QUEUE_MAX_SIZE 10
#define USBH_HID_POLL_MIN_NUM 10
/**@} end of group USBH_HID_Macros*/
/** @defgroup USBH_HID_Enumerates Enumerates
@{
*/
/**
* @brief USB HID state table
*/
typedef enum
{
USBH_HID_INIT = 0,
USBH_HID_IDLE = 1,
USBH_HID_SYNC,
USBH_HID_IN_DATA,
USBH_HID_POLL,
USBH_HID_OUT_DATA,
USBH_HID_BUSY,
USBH_HID_ERR,
} USBH_HID_STATE_T;
/**
* @brief USB HID request state table
*/
typedef enum
{
USBH_HID_REQ_INIT,
USBH_HID_REQ_IDLE,
USBH_HID_REQ_GET_REP_DESC,
USBH_HID_REQ_GET_HID_DESC,
USBH_HID_REQ_SET_IDLE,
USBH_HID_REQ_SET_PROTOCOL,
USBH_HID_REQ_SET_REPORT,
} USBH_HID_REQ_STA_T;
/**
* @brief USB HID report type
*/
typedef enum
{
HID_INPUT_REPORT = 1,
HID_OUTPUT_REPORT,
HID_FEATURE_REPORT,
} USBH_HID_REPORT_T;
/**
* @brief USB HID device class requests type
*/
typedef enum
{
USBH_HID_GET_REPORT = 1,
USBH_HID_GET_IDLE,
USBH_HID_GET_PROTOCOL,
USBH_HID_SET_REPORT = 9,
USBH_HID_SET_IDLE,
USBH_HID_SET_PROTOCOL,
} USBH_HID_REQ_TYPE_T;
/**@} end of group USBH_HID_Enumerates*/
/** @defgroup USBH_HID_Structures Structures
@{
*/
/**
* @brief USB HID descriptor
*/
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bcdHID[2];
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bReportDescriptorType;
uint8_t wDescriptorLength[2];
} USBH_HID_DESC_T;
/* Host HID class state handler function */
typedef USBH_STA_T(*USBH_HIDStateHandler_T)(USBH_INFO_T* usbInfo);
/**
* @brief USB host HID class handler
*/
typedef struct
{
USBH_STA_T(*InitHandler)(USBH_INFO_T* usbInfo);
USBH_STA_T(*DecodeHandler)(USBH_INFO_T* usbInfo);
} USBH_HID_CLASS_T;
/**
* @brief HID information management
*/
typedef struct
{
uint8_t* buffer;
USBH_HID_STATE_T state;
uint8_t classReqState;
uint8_t inChNum;
uint8_t outChNum;
uint8_t intOutEpAddr;
uint8_t intInEpAddr;
uint8_t epAddr;
uint8_t epSize;
uint16_t pollInterval;
uint8_t dataFlag;
USBH_HID_DESC_T desc;
USBH_HID_CLASS_T* callback;
uint32_t timer;
} USBH_HID_INFO_T;
extern USBH_CLASS_T USBH_HID_CLASS;
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
void USBH_HID_PollCallback(USBH_INFO_T* usbInfo);
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,342 @@
/*!
* @file usbh_hid_keyboard.h
*
* @brief USB host HID keyboard function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_HID_KEYBOARD_H_
#define _USBH_HID_KEYBOARD_H_
/* Includes */
#include "usbh_core.h"
#include "usbh_hid.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Macros Macros
@{
*/
#define USBH_HID_KEY_PRESSED_NUM_MAX 0x06
/**@} end of group USBH_HID_Macros*/
/** @defgroup USBH_HID_Enumerates Enumerates
@{
*/
/**
* @brief HID keyboard value
*/
typedef enum
{
KEYBOARD_NONE,
KEYBOARD_ERROR_ROLL_OVER,
KEYBOARD_POST_FAIL,
KEYBOARD_ERROR_UNDEFINED,
KEYBOARD_A,
KEYBOARD_B,
KEYBOARD_C,
KEYBOARD_D,
KEYBOARD_E,
KEYBOARD_F,
KEYBOARD_G,
KEYBOARD_H,
KEYBOARD_I,
KEYBOARD_J,
KEYBOARD_K,
KEYBOARD_L,
KEYBOARD_M,
KEYBOARD_N,
KEYBOARD_O,
KEYBOARD_P,
KEYBOARD_Q,
KEYBOARD_R,
KEYBOARD_S,
KEYBOARD_T,
KEYBOARD_U,
KEYBOARD_V,
KEYBOARD_W,
KEYBOARD_X,
KEYBOARD_Y,
KEYBOARD_Z,
KEYBOARD_1_EXCLAMATION,
KEYBOARD_2_AT,
KEYBOARD_3_NUMBER_SIGN,
KEYBOARD_4_DOLLAR,
KEYBOARD_5_PERCENT,
KEYBOARD_6_CARET,
KEYBOARD_7_AMPERSAND,
KEYBOARD_8_ASTERISK,
KEYBOARD_9_OPARENTHESIS,
KEYBOARD_10_CPARENTHESIS,
KEYBOARD_ENTER,
KEYBOARD_ESCAPE,
KEYBOARD_BACKSPACE,
KEYBOARD_TAB,
KEYBOARD_SPACEBAR,
KEYBOARD_MINUS_UNDERSCORE,
KEYBOARD_EQUAL_PLUS,
KEYBOARD_OBRACKET_AND_OBRACE,
KEYBOARD_CBRACKET_AND_CBRACE,
KEYBOARD_BACKSLASH_VERTICAL_BAR,
KEYBOARD_NONUS_NUMBER_SIGN_TILDE,
KEYBOARD_SEMICOLON_COLON,
KEYBOARD_SINGLE_AND_DOUBLE_QUOTE,
KEYBOARD_GRAVE_ACCENT_AND_TILDE,
KEYBOARD_COMMA_AND_LESS,
KEYBOARD_DOT_GREATER,
KEYBOARD_SLASH_QUESTION,
KEYBOARD_CAPS_LOCK,
KEYBOARD_F1,
KEYBOARD_F2,
KEYBOARD_F3,
KEYBOARD_F4,
KEYBOARD_F5,
KEYBOARD_F6,
KEYBOARD_F7,
KEYBOARD_F8,
KEYBOARD_F9,
KEYBOARD_F10,
KEYBOARD_F11,
KEYBOARD_F12,
KEYBOARD_PRINTSCREEN,
KEYBOARD_SCROLL_LOCK,
KEYBOARD_PAUSE,
KEYBOARD_INSERT,
KEYBOARD_HOME,
KEYBOARD_PAGEUP,
KEYBOARD_DELETE,
KEYBOARD_END1,
KEYBOARD_PAGEDOWN,
KEYBOARD_RIGHTARROW,
KEYBOARD_LEFTARROW,
KEYBOARD_DOWNARROW,
KEYBOARD_UPARROW,
KEYBOARD_KEYBOARDPAD_NUM_LOCK_AND_CLEAR,
KEYBOARD_KEYBOARDPAD_SLASH,
KEYBOARD_KEYBOARDPAD_ASTERIKS,
KEYBOARD_KEYBOARDPAD_MINUS,
KEYBOARD_KEYBOARDPAD_PLUS,
KEYBOARD_KEYBOARDPAD_ENTER,
KEYBOARD_KEYBOARDPAD_1_END,
KEYBOARD_KEYBOARDPAD_2_DOWN_ARROW,
KEYBOARD_KEYBOARDPAD_3_PAGEDN,
KEYBOARD_KEYBOARDPAD_4_LEFT_ARROW,
KEYBOARD_KEYBOARDPAD_5,
KEYBOARD_KEYBOARDPAD_6_RIGHT_ARROW,
KEYBOARD_KEYBOARDPAD_7_HOME,
KEYBOARD_KEYBOARDPAD_8_UP_ARROW,
KEYBOARD_KEYBOARDPAD_9_PAGEUP,
KEYBOARD_KEYBOARDPAD_0_INSERT,
KEYBOARD_KEYBOARDPAD_DECIMAL_SEPARATOR_DELETE,
KEYBOARD_NONUS_BACK_SLASH_VERTICAL_BAR,
KEYBOARD_APPLICATION,
KEYBOARD_POWER,
KEYBOARD_KEYBOARDPAD_EQUAL,
KEYBOARD_F13,
KEYBOARD_F14,
KEYBOARD_F15,
KEYBOARD_F16,
KEYBOARD_F17,
KEYBOARD_F18,
KEYBOARD_F19,
KEYBOARD_F20,
KEYBOARD_F21,
KEYBOARD_F22,
KEYBOARD_F23,
KEYBOARD_F24,
KEYBOARD_EXECUTE,
KEYBOARD_HELP,
KEYBOARD_MENU,
KEYBOARD_SELECT,
KEYBOARD_STOP,
KEYBOARD_AGAIN,
KEYBOARD_UNDO,
KEYBOARD_CUT,
KEYBOARD_COPY,
KEYBOARD_PASTE,
KEYBOARD_FIND,
KEYBOARD_MUTE,
KEYBOARD_VOLUME_UP,
KEYBOARD_VOLUME_DOWN,
KEYBOARD_LOCKING_CAPS_LOCK,
KEYBOARD_LOCKING_NUM_LOCK,
KEYBOARD_LOCKING_SCROLL_LOCK,
KEYBOARD_KEYBOARDPAD_COMMA,
KEYBOARD_KEYBOARDPAD_EQUAL_SIGN,
KEYBOARD_INTERNATIONAL1,
KEYBOARD_INTERNATIONAL2,
KEYBOARD_INTERNATIONAL3,
KEYBOARD_INTERNATIONAL4,
KEYBOARD_INTERNATIONAL5,
KEYBOARD_INTERNATIONAL6,
KEYBOARD_INTERNATIONAL7,
KEYBOARD_INTERNATIONAL8,
KEYBOARD_INTERNATIONAL9,
KEYBOARD_LANG1,
KEYBOARD_LANG2,
KEYBOARD_LANG3,
KEYBOARD_LANG4,
KEYBOARD_LANG5,
KEYBOARD_LANG6,
KEYBOARD_LANG7,
KEYBOARD_LANG8,
KEYBOARD_LANG9,
KEYBOARD_ALTERNATE_ERASE,
KEYBOARD_SYSREQ,
KEYBOARD_CANCEL,
KEYBOARD_CLEAR,
KEYBOARD_PRIOR,
KEYBOARD_RETURN,
KEYBOARD_SEPARATOR,
KEYBOARD_OUT,
KEYBOARD_OPER,
KEYBOARD_CLEAR_AGAIN,
KEYBOARD_CRSEL,
KEYBOARD_EXSEL,
KEYBOARD_RESERVED1,
KEYBOARD_RESERVED2,
KEYBOARD_RESERVED3,
KEYBOARD_RESERVED4,
KEYBOARD_RESERVED5,
KEYBOARD_RESERVED6,
KEYBOARD_RESERVED7,
KEYBOARD_RESERVED8,
KEYBOARD_RESERVED9,
KEYBOARD_RESERVED10,
KEYBOARD_RESERVED11,
KEYBOARD_KEYBOARDPAD_00,
KEYBOARD_KEYBOARDPAD_000,
KEYBOARD_THOUSANDS_SEPARATOR,
KEYBOARD_DECIMAL_SEPARATOR,
KEYBOARD_CURRENCY_UNIT,
KEYBOARD_CURRENCY_SUB_UNIT,
KEYBOARD_KEYBOARDPAD_OPARENTHESIS,
KEYBOARD_KEYBOARDPAD_CPARENTHESIS,
KEYBOARD_KEYBOARDPAD_OBRACE,
KEYBOARD_KEYBOARDPAD_CBRACE,
KEYBOARD_KEYBOARDPAD_TAB,
KEYBOARD_KEYBOARDPAD_BACKSPACE,
KEYBOARD_KEYBOARDPAD_A,
KEYBOARD_KEYBOARDPAD_B,
KEYBOARD_KEYBOARDPAD_C,
KEYBOARD_KEYBOARDPAD_D,
KEYBOARD_KEYBOARDPAD_E,
KEYBOARD_KEYBOARDPAD_F,
KEYBOARD_KEYBOARDPAD_XOR,
KEYBOARD_KEYBOARDPAD_CARET,
KEYBOARD_KEYBOARDPAD_PERCENT,
KEYBOARD_KEYBOARDPAD_LESS,
KEYBOARD_KEYBOARDPAD_GREATER,
KEYBOARD_KEYBOARDPAD_AMPERSAND,
KEYBOARD_KEYBOARDPAD_LOGICAL_AND,
KEYBOARD_KEYBOARDPAD_VERTICAL_BAR,
KEYBOARD_KEYBOARDPAD_LOGIACL_OR,
KEYBOARD_KEYBOARDPAD_COLON,
KEYBOARD_KEYBOARDPAD_NUMBER_SIGN,
KEYBOARD_KEYBOARDPAD_SPACE,
KEYBOARD_KEYBOARDPAD_AT,
KEYBOARD_KEYBOARDPAD_EXCLAMATION_MARK,
KEYBOARD_KEYBOARDPAD_MEMORY_STORE,
KEYBOARD_KEYBOARDPAD_MEMORY_RECALL,
KEYBOARD_KEYBOARDPAD_MEMORY_CLEAR,
KEYBOARD_KEYBOARDPAD_MEMORY_ADD,
KEYBOARD_KEYBOARDPAD_MEMORY_SUBTRACT,
KEYBOARD_KEYBOARDPAD_MEMORY_MULTIPLY,
KEYBOARD_KEYBOARDPAD_MEMORY_DIVIDE,
KEYBOARD_KEYBOARDPAD_PLUSMINUS,
KEYBOARD_KEYBOARDPAD_CLEAR,
KEYBOARD_KEYBOARDPAD_CLEAR_ENTRY,
KEYBOARD_KEYBOARDPAD_BINARY,
KEYBOARD_KEYBOARDPAD_OCTAL,
KEYBOARD_KEYBOARDPAD_DECIMAL,
KEYBOARD_KEYBOARDPAD_HEXADECIMAL,
KEYBOARD_RESERVED12,
KEYBOARD_RESERVED13,
KEYBOARD_LEFTCONTROL,
KEYBOARD_LEFTSHIFT,
KEYBOARD_LEFTALT,
KEYBOARD_LEFT_GUI,
KEYBOARD_RIGHTCONTROL,
KEYBOARD_RIGHTSHIFT,
KEYBOARD_RIGHTALT,
KEYBOARD_RIGHT_GUI,
} USBH_HID_KEYBOARD_VALUE_T;
/**@} end of group USBH_HID_Enumerates*/
/** @defgroup USBH_HID_Structures Structures
@{
*/
/**
* @brief HID keyboard report information
*/
typedef struct
{
uint32_t data[2];
uint32_t rxBuffer[2];
} USBH_HID_KEYBOARD_REPORT_T;
/**
* @brief HID keyboard information management
*/
typedef struct
{
uint8_t ctrlLeft;
uint8_t shiftLeft;
uint8_t altLeft;
uint8_t winLeft;
uint8_t ctrlRight;
uint8_t shiftRight;
uint8_t altRight;
uint8_t winRight;
uint8_t key[USBH_HID_KEY_PRESSED_NUM_MAX];
USBH_HID_KEYBOARD_REPORT_T report;
} USBH_HID_KEYBOARD_INFO_T;
extern USBH_HID_CLASS_T USBH_HID_KEYBOARD_Handler;
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
USBH_STA_T USBH_HID_KeyBoardInit(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_HID_KeyboardDecode(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_HID_KeyboardCallback(USBH_INFO_T* usbInfo);
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,92 @@
/*!
* @file usbh_hid_mouse.h
*
* @brief USB host HID mouse function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_HID_MOUSE_H_
#define _USBH_HID_MOUSE_H_
/* Includes */
#include "usbh_core.h"
#include "usbh_hid.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Macros Macros
@{
*/
#define USBH_HID_MOUSE_BUTTON_MAX_NUM 3
/**@} end of group USBH_HID_Macros*/
/** @defgroup USBH_HID_Structures Structures
@{
*/
/**
* @brief HID mouse report information
*/
typedef struct
{
uint32_t data[2];
uint32_t rxBuffer[2];
} USBH_HID_MOUSE_REPORT_T;
/**
* @brief HID mouse information management
*/
typedef struct
{
uint8_t x;
uint8_t y;
uint8_t z;
uint8_t button[USBH_HID_MOUSE_BUTTON_MAX_NUM];
USBH_HID_MOUSE_REPORT_T report;
} USBH_HID_MOUSE_INFO_T;
extern USBH_HID_MOUSE_INFO_T usbHostHidMouse;
extern USBH_HID_CLASS_T USBH_HID_MOUSE_Handler;
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
USBH_STA_T USBH_HID_MouseInit(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_HID_MouseDecode(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_HID_MouseCallback(USBH_INFO_T* usbInfo);
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,952 @@
/*!
* @file usbh_hid.h
*
* @brief USB HID core function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_hid.h"
#include "usbh_hid_mouse.h"
#include "usbh_hid_keyboard.h"
#include "usbh_stdReq.h"
#include "usbh_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
static USBH_STA_T USBH_HID_ClassInitHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_ClassDeInitHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_ClassReqHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_SOFHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_CoreHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_InitHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_IdleHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_SyncHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_InDataHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_PollingHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_OutDataHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_BusyHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_HID_ErrorHandler(USBH_INFO_T* usbInfo);
/**@} end of group USBH_HID_Functions */
/** @defgroup USBH_HID_Structures Structures
@{
*/
/* HID class handler */
USBH_CLASS_T USBH_HID_CLASS =
{
"Class HID",
USBH_CLASS_HID,
NULL,
USBH_HID_ClassInitHandler,
USBH_HID_ClassDeInitHandler,
USBH_HID_ClassReqHandler,
USBH_HID_CoreHandler,
USBH_HID_SOFHandler,
};
/* USB host HID state handler function */
USBH_HIDStateHandler_T USBH_HID_Handler[] =
{
USBH_HID_InitHandler,
USBH_HID_IdleHandler,
USBH_HID_SyncHandler,
USBH_HID_InDataHandler,
USBH_HID_PollingHandler,
USBH_HID_OutDataHandler,
USBH_HID_BusyHandler,
USBH_HID_ErrorHandler,
};
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
/*!
* @brief Config HID get report descriptor request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type
*
* @param reportType : type of report
*
* @param reportID : ID of report
*
* @param buffer : report buffer
*
* @param length : report length
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_REQ_GetRepDescriptor(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t reportType, uint8_t reportID, \
uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_HID_GET_REPORT;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = reportID;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = reportType;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = length & 0xFF;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = length >> 8;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, buffer, length);
return usbStatus;
}
/*!
* @brief USB host HID set idle request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param reportID : traget report ID
*
* @param duration : duration for idle request
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_REQ_SetIdle(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t reportID, uint8_t duration)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_HID_SET_IDLE;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = reportID;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = duration;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief USB host HID set protocol request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param protocol : boot / report protocol
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_REQ_SetProtocol(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t protocol)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_HID_SET_PROTOCOL;
if (protocol)
{
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = 0;
}
else
{
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = 1;
}
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief USB host get HID description
*
* @param usbInfo : usb handler information
*
* @param desLength : length of description
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_GetHIDDesc(USBH_INFO_T* usbInfo, uint16_t desLength)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_GetDescriptor(usbInfo, ((USBH_REQ_DIR_IN << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_INTERFACE)), \
USBH_DESC_HID_REPORT,
usbInfo->devInfo.data,
desLength);
return usbStatus;
}
/*!
* @brief USB host get HID report description
*
* @param usbInfo : usb handler information
*
* @param reportType : type of report
*
* @param reportID : ID of report
*
* @param buffer : report buffer
*
* @param length : report length
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_GetReportDesc(USBH_INFO_T* usbInfo, uint8_t reportType, \
uint8_t reportID, uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_HID_REQ_GetRepDescriptor(usbInfo, ((USBH_REQ_DIR_IN << 7) | \
(USBH_REQ_TYPE_CLASS << 5) | \
(USBH_RECIPIENT_INTERFACE)), \
reportType,
reportID,
buffer,
length);
return usbStatus;
}
/*!
* @brief USB host set HID idle
*
* @param usbInfo : usb handler information
*
* @param reportID : traget report ID
*
* @param duration : duration for idle request
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_SetIdle(USBH_INFO_T* usbInfo, uint8_t reportID, uint8_t duration)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_HID_REQ_SetIdle(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_CLASS << 5) | \
(USBH_RECIPIENT_INTERFACE)),
reportID, \
duration);
return usbStatus;
}
/*!
* @brief USB host set HID protocol
*
* @param usbInfo : usb handler information
*
* @param protocol : boot / report protocol
*
* @retval usb host status
*/
static USBH_STA_T USBH_HID_SetProtocol(USBH_INFO_T* usbInfo, uint8_t protocol)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_HID_REQ_SetProtocol(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_CLASS << 5) | \
(USBH_RECIPIENT_INTERFACE)),
protocol);
return usbStatus;
}
/*!
* @brief USB host HID init handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_InitHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
usbHostHID->callback->InitHandler(usbInfo);
/* Notify User */
usbInfo->userCallback(usbInfo, USBH_USER_CLASS_LAUNCHED);
usbHostHID->state = USBH_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB host HID idle handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_IdleHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t reqStatus = USBH_BUSY;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_IdleHandler");
reqStatus = USBH_HID_GetReportDesc(usbInfo,
HID_INPUT_REPORT,
0,
usbHostHID->buffer,
usbHostHID->epSize);
switch (reqStatus)
{
case USBH_OK:
usbHostHID->state = USBH_HID_SYNC;
break;
case USBH_BUSY:
usbHostHID->state = USBH_HID_IDLE;
usbStatus = USBH_OK;
break;
case USBH_ERR_NOT_SUP:
usbHostHID->state = USBH_HID_SYNC;
usbStatus = USBH_OK;
break;
default:
usbHostHID->state = USBH_HID_ERR;
usbStatus = USBH_FAIL;
break;
}
return usbStatus;
}
/*!
* @brief USB host HID SYNC handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_SyncHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_SyncHandler");
/* Sync with SOF */
if (usbInfo->timer % 2)
{
usbHostHID->state = USBH_HID_IN_DATA;
}
return usbStatus;
}
/*!
* @brief USB host HID get data handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_InDataHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_InDataHandler");
USBH_IntReceiveDataReq(usbInfo, usbHostHID->inChNum, usbHostHID->buffer, \
usbHostHID->epSize);
usbHostHID->state = USBH_HID_POLL;
usbHostHID->timer = usbInfo->timer;
usbHostHID->dataFlag = DISABLE;
return usbStatus;
}
/*!
* @brief USB host HID polling handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_PollingHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t usbUrbStatus;
uint8_t reqStatus = USBH_BUSY;
uint32_t xferSize;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_PollingHandler");
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbHostHID->inChNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
xferSize = USBH_ReadLastXferSizeCallback(usbInfo, usbHostHID->inChNum);
if ((xferSize != 0) && (usbHostHID->dataFlag == DISABLE))
{
usbHostHID->dataFlag = ENABLE;
//USBH_HID_WriteFifo(&usbHostHID->fifo, usbHostHID->buffer, usbHostHID->epSize);
/* HID event callback */
USBH_HID_PollCallback(usbInfo);
}
break;
case USB_URB_STALL:
reqStatus = USBH_ClearFeature(usbInfo, usbHostHID->epAddr);
switch (reqStatus)
{
case USBH_OK:
usbHostHID->state = USBH_HID_IN_DATA;
break;
default:
break;
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host HID send data handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_OutDataHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
return usbStatus;
}
/*!
* @brief USB host HID busy handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_BusyHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_USR_Debug("USBH_HID_BusyHandler");
return usbStatus;
}
/*!
* @brief USB host HID error handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_ErrorHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_USR_Debug("USBH_HID_ErrorHandler");
return usbStatus;
}
/*!
* @brief Parse HID descriptor
*
* @param hidDesc : HID descriptor
*
* @param buffer : source data of configuration descriptor
*
* @retval usb host status
*/
USBH_STA_T USBH_HidDescParse(USBH_HID_DESC_T* hidDesc, uint8_t* buffer)
{
USBH_STA_T usbStatus = USBH_OK;
uint16_t totalLenTemp = 0;
uint8_t subLen = 0;
uint16_t parseIndex = 0;
totalLenTemp = *(uint8_t*)(buffer + 2) | (*(uint8_t*)(buffer + 3) << 8);
totalLenTemp = ((totalLenTemp) < (CFG_DESC_MAX_LEN) ? (totalLenTemp) : (CFG_DESC_MAX_LEN));
if (totalLenTemp > STD_CFG_DESC_SIZE)
{
parseIndex = STD_CFG_DESC_SIZE;
while (totalLenTemp > parseIndex)
{
subLen = buffer[parseIndex];
switch (buffer[parseIndex + 1])
{
case USBH_DESC_HID:
hidDesc->bLength = buffer[parseIndex + 0];
hidDesc->bDescriptorType = buffer[parseIndex + 1];
hidDesc->bcdHID[0] = buffer[parseIndex + 2];
hidDesc->bcdHID[1] = buffer[parseIndex + 3];
hidDesc->bCountryCode = buffer[parseIndex + 4];
hidDesc->bNumDescriptors = buffer[parseIndex + 5];
hidDesc->bReportDescriptorType = buffer[parseIndex + 6];
hidDesc->wDescriptorLength[0] = buffer[parseIndex + 7];
hidDesc->wDescriptorLength[1] = buffer[parseIndex + 8];
break;
default:
break;
}
parseIndex += subLen;
/* To avoid some useless data left */
if ((totalLenTemp - parseIndex) < STD_EP_DESC_SIZE)
{
break;
}
}
}
return usbStatus;
}
/*!
* @brief USB host HID configuration handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_ClassInitHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID;
uint8_t itfNum;
uint8_t subClass;
uint8_t classInterface;
uint8_t protocolInterface;
uint16_t mps;
uint8_t epAddr;
uint8_t pollInterval;
uint8_t epNum;
uint8_t epDir;
USBH_USR_Debug("USBH_HID_ClassInitHandler");
/* Link class data */
usbInfo->activeClass->classData = (USBH_HID_INFO_T*)malloc(sizeof(USBH_HID_INFO_T));
usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
memset(usbHostHID, 0, sizeof(USBH_HID_INFO_T));
itfNum = USBH_ReadConfigurationItfNum(usbInfo);
while (itfNum--)
{
subClass = USBH_ReadInterfaceSubClass(usbInfo, itfNum);
if (subClass != USBH_HID_BOOT_CODE)
{
USBH_USR_Debug("Interface is not valid");
usbStatus = USBH_FAIL;
continue;
}
classInterface = USBH_ReadInterfaceClass(usbInfo, itfNum);
if (classInterface != USBH_CLASS_HID)
{
USBH_USR_Debug("Class type is not support");
usbStatus = USBH_ERR_NOT_SUP;
continue;
}
protocolInterface = USBH_ReadInterfaceProtocol(usbInfo, itfNum);
/* Decode class protocol */
switch (protocolInterface)
{
case USBH_HID_KEYBOARD_BOOT_CODE:
USBH_USR_LOG("Register keyboard class init");
usbHostHID->callback = &USBH_HID_KEYBOARD_Handler;
usbStatus = USBH_OK;
break;
case USBH_HID_MOUSE_BOOT_CODE:
USBH_USR_LOG("Register mouse class init");
usbHostHID->callback = &USBH_HID_MOUSE_Handler;
usbStatus = USBH_OK;
break;
default:
USBH_USR_LOG("Protocol is not support");
usbStatus = USBH_FAIL;
break;
}
epAddr = USBH_ReadEndpointAddress(usbInfo, itfNum, 0);
mps = USBH_ReadEndpointMPS(usbInfo, itfNum, 0);
pollInterval = USBH_ReadEndpointInterval(usbInfo, itfNum, 0);
usbHostHID->epAddr = epAddr;
usbHostHID->epSize = mps;
usbHostHID->pollInterval = pollInterval;
usbHostHID->state = USBH_HID_INIT;
usbHostHID->classReqState = USBH_HID_REQ_INIT;
if (usbHostHID->pollInterval < USBH_HID_POLL_MIN_NUM)
{
usbHostHID->pollInterval = USBH_HID_POLL_MIN_NUM;
}
epNum = USBH_ReadInterfaceEpNum(usbInfo, itfNum);
if (epNum > ENDPOINT_DESC_MAX_NUM)
{
epNum = ENDPOINT_DESC_MAX_NUM;
}
while (epNum--)
{
/* Get endpoint and size */
epDir = epAddr & 0x80;
if (epDir)
{
usbHostHID->intInEpAddr = USBH_ReadEndpointAddress(usbInfo, itfNum, epNum);
usbHostHID->inChNum = USBH_CH_AllocChannel(usbInfo, usbHostHID->intInEpAddr);
USBH_OpenChannelCallback(usbInfo, usbHostHID->inChNum,
usbHostHID->intInEpAddr,
usbInfo->devInfo.address,
usbInfo->devInfo.speed,
EP_TYPE_INTERRUPT,
usbHostHID->epSize);
USBH_ConfigDataPidCallback(usbInfo, usbHostHID->inChNum, 0);
}
else
{
usbHostHID->intOutEpAddr = USBH_ReadEndpointAddress(usbInfo, itfNum, epNum);
usbHostHID->outChNum = USBH_CH_AllocChannel(usbInfo, usbHostHID->intOutEpAddr);
USBH_OpenChannelCallback(usbInfo, usbHostHID->outChNum,
usbHostHID->intOutEpAddr,
usbInfo->devInfo.address,
usbInfo->devInfo.speed,
EP_TYPE_INTERRUPT,
usbHostHID->epSize);
USBH_ConfigDataPidCallback(usbInfo, usbHostHID->outChNum, 0);
}
}
}
return usbStatus;
}
/*!
* @brief USB host HID class reset handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_ClassDeInitHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_ClassDeInitHandler");
if (usbHostHID->inChNum != 0)
{
USBH_CloseChannelCallback(usbInfo, usbHostHID->inChNum);
USBH_CH_FreeChannel(usbInfo, usbHostHID->inChNum);
usbHostHID->inChNum = 0;
}
if (usbHostHID->outChNum != 0)
{
USBH_CloseChannelCallback(usbInfo, usbHostHID->outChNum);
USBH_CH_FreeChannel(usbInfo, usbHostHID->outChNum);
usbHostHID->outChNum = 0;
}
if (usbInfo->activeClass->classData != NULL)
{
free(usbInfo->activeClass->classData);
usbInfo->activeClass->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB host HID class reguest handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_ClassReqHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t reqStatus = USBH_BUSY;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
uint16_t descLength;
USBH_USR_Debug("USBH_HID_ClassReqHandler");
switch (usbHostHID->classReqState)
{
case USBH_HID_REQ_IDLE:
break;
case USBH_HID_REQ_INIT:
case USBH_HID_REQ_GET_HID_DESC:
USBH_HidDescParse(&usbHostHID->desc, usbInfo->devInfo.desc.cfgDescBuf);
usbHostHID->classReqState = USBH_HID_REQ_GET_REP_DESC;
break;
case USBH_HID_REQ_GET_REP_DESC:
descLength = usbHostHID->desc.wDescriptorLength[0] | usbHostHID->desc.wDescriptorLength[1] << 8;
reqStatus = USBH_HID_GetHIDDesc(usbInfo, descLength);
switch (reqStatus)
{
case USBH_OK:
usbHostHID->classReqState = USBH_HID_REQ_SET_IDLE;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("Class Req Error: Get report descriptor failed");
usbStatus = USBH_FAIL;
break;
default:
break;
}
break;
case USBH_HID_REQ_SET_IDLE:
reqStatus = USBH_HID_SetIdle(usbInfo, 0, 0);
switch (reqStatus)
{
case USBH_OK:
usbHostHID->classReqState = USBH_HID_REQ_SET_PROTOCOL;
break;
case USBH_ERR_NOT_SUP:
usbHostHID->classReqState = USBH_HID_REQ_SET_PROTOCOL;
break;
default:
break;
}
break;
case USBH_HID_REQ_SET_PROTOCOL:
reqStatus = USBH_HID_SetProtocol(usbInfo, 0);
switch (reqStatus)
{
case USBH_OK:
usbHostHID->classReqState = USBH_HID_REQ_IDLE;
usbStatus = USBH_OK;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("Class Req Error: Set protocol failed");
usbStatus = USBH_FAIL;
break;
default:
break;
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host HID SOF handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_SOFHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
uint32_t interval;
USBH_USR_Debug("USBH_HID_SOFHandler");
if (usbHostHID->state == USBH_HID_POLL)
{
interval = usbInfo->timer - usbHostHID->timer;
if (interval >= usbHostHID->pollInterval)
{
usbHostHID->state = USBH_HID_IN_DATA;
}
}
return usbStatus;
}
/*!
* @brief USB host HID handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_HID_CoreHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_HID_CoreHandler");
usbStatus = USBH_HID_Handler[usbHostHID->state](usbInfo);
return usbStatus;
}
/*!
* @brief USB host HID handler
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
__weak void USBH_HID_PollCallback(USBH_INFO_T* usbInfo)
{
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
/* callback interface */
usbHostHID->callback->DecodeHandler(usbInfo);
}
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,192 @@
/*!
* @file usbh_hid_keyboard.c
*
* @brief USB host HID keyboard function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_hid_keyboard.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Structures Structures
@{
*/
USBH_HID_KEYBOARD_INFO_T usbHostHidKeyboard;
/* HID keyboard class handler */
USBH_HID_CLASS_T USBH_HID_KEYBOARD_Handler =
{
USBH_HID_KeyBoardInit,
USBH_HID_KeyboardDecode,
};
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
/*!
* @brief USB host HID init keyboard
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_HID_KeyBoardInit(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
uint16_t i;
usbHostHidKeyboard.ctrlLeft = 0;
usbHostHidKeyboard.altLeft = 0;
usbHostHidKeyboard.shiftLeft = 0;
usbHostHidKeyboard.winLeft = 0;
usbHostHidKeyboard.ctrlRight = 0;
usbHostHidKeyboard.altRight = 0;
usbHostHidKeyboard.shiftRight = 0;
usbHostHidKeyboard.winRight = 0;
for (i = 0; i < USBH_HID_KEY_PRESSED_NUM_MAX; i++)
{
usbHostHidKeyboard.key[i] = 0;
}
for (i = 0; i < (sizeof(usbHostHidKeyboard.report.data) \
/ sizeof(usbHostHidKeyboard.report.data[0])); i++)
{
usbHostHidKeyboard.report.data[i] = 0;
usbHostHidKeyboard.report.rxBuffer[i] = 0;
}
if (usbHostHID->epSize > sizeof(usbHostHidKeyboard.report.data))
{
usbHostHID->epSize = (uint16_t)sizeof(usbHostHidKeyboard.report.data);
}
/* Init buffer point */
usbHostHID->buffer = (uint8_t*)(void*)usbHostHidKeyboard.report.data;
return usbStatus;
}
/*!
* @brief USB host HID decode keyboard
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_HID_KeyboardDecode(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t funKeyTemp;
uint8_t i;
if ((usbHostHidKeyboard.report.data[1] == 0x01010101) && \
(usbHostHidKeyboard.report.data[0] == 0x01010000))
{
USBH_USR_LOG("Keyboard do not support this operation");
}
else
{
for (i = 2; i < 2 + USBH_HID_KEY_PRESSED_NUM_MAX; i++)
{
funKeyTemp = *((uint8_t*)(void*)usbHostHidKeyboard.report.data + i);
if ((funKeyTemp == KEYBOARD_ERROR_ROLL_OVER) || \
(funKeyTemp == KEYBOARD_POST_FAIL) || \
(funKeyTemp == KEYBOARD_ERROR_UNDEFINED))
{
return USBH_FAIL;
}
}
funKeyTemp = *((uint8_t*)(void*)usbHostHidKeyboard.report.data + 0);
usbHostHidKeyboard.ctrlLeft = (funKeyTemp & 0x01) > 0 ? 1 : 0;
usbHostHidKeyboard.shiftLeft = (funKeyTemp & 0x02) > 0 ? 1 : 0;
usbHostHidKeyboard.altLeft = (funKeyTemp & 0x04) > 0 ? 1 : 0;
usbHostHidKeyboard.winLeft = (funKeyTemp & 0x08) > 0 ? 1 : 0;
usbHostHidKeyboard.ctrlRight = (funKeyTemp & 0x10) > 0 ? 1 : 0;
usbHostHidKeyboard.shiftRight = (funKeyTemp & 0x20) > 0 ? 1 : 0;
usbHostHidKeyboard.altRight = (funKeyTemp & 0x40) > 0 ? 1 : 0;
usbHostHidKeyboard.winRight = (funKeyTemp & 0x80) > 0 ? 1 : 0;
for (i = 0; i < USBH_HID_KEY_PRESSED_NUM_MAX; i++)
{
usbHostHidKeyboard.key[i] = *((uint8_t*)(void*)usbHostHidKeyboard.report.data + i + 2);
}
/* Process keyboard data */
USBH_HID_KeyboardCallback(usbInfo);
}
return usbStatus;
}
/*!
* @brief USB host HID keyboard data process
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
__weak USBH_STA_T USBH_HID_KeyboardCallback(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t i;
USBH_USR_LOG("CTRL L:%02X", usbHostHidKeyboard.ctrlLeft);
USBH_USR_LOG("SHIFT L:%02X", usbHostHidKeyboard.shiftLeft);
USBH_USR_LOG("ALT L:%02X", usbHostHidKeyboard.altLeft);
USBH_USR_LOG("WIN L:%02X", usbHostHidKeyboard.winLeft);
USBH_USR_LOG("CTRL R:%02X", usbHostHidKeyboard.ctrlRight);
USBH_USR_LOG("SHIFT R:%02X", usbHostHidKeyboard.shiftRight);
USBH_USR_LOG("ALT R:%02X", usbHostHidKeyboard.altRight);
USBH_USR_LOG("WIN R:%02X", usbHostHidKeyboard.winRight);
for (i = 0; i < USBH_HID_KEY_PRESSED_NUM_MAX; i++)
{
USBH_USR_LOG("KEY[%d] :%02X", i, usbHostHidKeyboard.key[i]);
}
USBH_USR_LOG(" ");
return usbStatus;
}
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,154 @@
/*!
* @file usbh_hid_mouse.c
*
* @brief USB host HID mouse function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_hid_mouse.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_HID_Class
@{
*/
/** @defgroup USBH_HID_Structures Structures
@{
*/
USBH_HID_MOUSE_INFO_T usbHostHidMouse;
/* HID mouse class handler */
USBH_HID_CLASS_T USBH_HID_MOUSE_Handler =
{
USBH_HID_MouseInit,
USBH_HID_MouseDecode,
};
/**@} end of group USBH_HID_Structures*/
/** @defgroup USBH_HID_Functions Functions
@{
*/
/*!
* @brief USB host HID init mouse
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_HID_MouseInit(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_HID_INFO_T* usbHostHID = (USBH_HID_INFO_T*)usbInfo->activeClass->classData;
uint16_t i;
usbHostHidMouse.x = 0;
usbHostHidMouse.y = 0;
for (i = 0; i < USBH_HID_MOUSE_BUTTON_MAX_NUM; i++)
{
usbHostHidMouse.button[i] = 0;
}
for (i = 0; i < (sizeof(usbHostHidMouse.report.data) \
/ sizeof(usbHostHidMouse.report.data[0])); i++)
{
usbHostHidMouse.report.data[i] = 0;
usbHostHidMouse.report.rxBuffer[i] = 0;
}
if (usbHostHID->epSize > sizeof(usbHostHidMouse.report.data))
{
usbHostHID->epSize = (uint16_t)sizeof(usbHostHidMouse.report.data);
}
/* Init buffer point */
usbHostHID->buffer = (uint8_t*)(void*)usbHostHidMouse.report.data;
return usbStatus;
}
/*!
* @brief USB host HID decode mouse
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_HID_MouseDecode(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t buttonTemp;
uint8_t coordinateX;
uint8_t coordinateY;
uint8_t coordinateZ;
buttonTemp = *((uint8_t*)(void*)usbHostHidMouse.report.data + 0);
coordinateX = *((uint8_t*)(void*)usbHostHidMouse.report.data + 1);
coordinateY = *((uint8_t*)(void*)usbHostHidMouse.report.data + 2);
coordinateZ = *((uint8_t*)(void*)usbHostHidMouse.report.data + 3);
usbHostHidMouse.button[0] = (buttonTemp & 0x01) > 0 ? 1 : 0;
usbHostHidMouse.button[1] = (buttonTemp & 0x02) > 0 ? 1 : 0;
usbHostHidMouse.button[2] = (buttonTemp & 0x04) > 0 ? 1 : 0;
usbHostHidMouse.x = coordinateX;
usbHostHidMouse.y = coordinateY;
usbHostHidMouse.z = coordinateZ;
/* Process mouse data */
USBH_HID_MouseCallback(usbInfo);
return usbStatus;
}
/*!
* @brief USB host HID mouse data process
*
* @param usbInfo: usb host information
*
* @retval USB host operation status
*/
__weak USBH_STA_T USBH_HID_MouseCallback(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_USR_LOG("x:%02X", usbHostHidMouse.x);
USBH_USR_LOG("y:%02X", usbHostHidMouse.y);
USBH_USR_LOG("z:%02X", usbHostHidMouse.z);
USBH_USR_LOG("b1:%02X", usbHostHidMouse.button[0]);
USBH_USR_LOG("b2:%02X", usbHostHidMouse.button[1]);
USBH_USR_LOG("b3:%02X", usbHostHidMouse.button[2]);
USBH_USR_LOG(" ");
return usbStatus;
}
/**@} end of group USBH_HID_Functions */
/**@} end of group USBH_HID_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,167 @@
/*!
* @file usbh_msc.h
*
* @brief usb host msc class handler header file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_MSC_H_
#define _USBH_MSC_H_
/* Includes */
#include "usbh_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_MSC_Class
@{
*/
/** @defgroup USBH_MSC_Macros Macros
@{
*/
#define USBH_CLASS_GET_MAX_LUN 0xFE
#define USBH_CLASS_BOT_RESET 0xFF
#define USBH_SUPPORTED_LUN_MAX 0x02
#define USBH_MSC_SCSI_CLASS_CODE 0x06
/**@} end of group USBH_MSC_Macros*/
/** @defgroup USBH_MSC_Enumerates Enumerates
@{
*/
/**
* @brief MSC state table
*/
typedef enum
{
USBH_MSC_INIT = 0,
USBH_MSC_IDLE = 1,
USBH_MSC_INQUIRY,
USBH_MSC_TEST_UNIT_READY,
USBH_MSC_REQUEST_SENSE,
USBH_MSC_READ_CAPACITY,
USBH_MSC_UNRECOVERED_STATE,
USBH_MSC_RW_READ,
USBH_MSC_RW_WRITE,
USBH_MSC_RW_REQIEST_SENSE,
} USBH_MSC_STATE_T;
/**
* @brief MSC error state type
*/
typedef enum
{
USBH_MSC_OK,
USBH_MSC_BUSY,
USBH_MSC_ERR,
} USBH_MSC_ERR_STATE_T;
/**
* @brief MSC class request state table
*/
typedef enum
{
USBH_MSC_REQ_GET_MAX_LUN,
USBH_MSC_REQ_BOT_RESET,
USBH_MSC_REQ_CTRL_ERROR
} USBH_MSC_REQ_STATE_T;
/**
* @brief MSC protocol code
*/
typedef enum
{
USBH_MSC_PROTOCOL_CBI_00 = 0x00,
USBH_MSC_PROTOCOL_CBI_01 = 0x01,
USBH_MSC_PROTOCOL_BBB = 0x50,
USBH_MSC_PROTOCOL_UAS = 0x62
} USBH_MSC_PROTOCOL_CODE_T;
/**@} end of group USBH_MSC_Enumerates*/
/** @defgroup USBH_MSC_Structures Structures
@{
*/
/**
* @brief MSC Storage info
*/
typedef struct
{
USBH_SCSI_READ_CAPACITY_REQ_T capacity;
USBH_SCSI_INQUIRY_REQ_T inquiryReq;
USBH_SCSI_SENSE_REQ_T sense;
USBH_MSC_STATE_T state;
uint8_t changeState;
uint8_t preReadyState;
USBH_MSC_ERR_STATE_T errState;
} USBH_MSC_STORAGE_INFO_T;
/* Host MSC class state handler function */
typedef USBH_STA_T(*USBH_MscStateHandler_T)(USBH_INFO_T* usbInfo, uint8_t lun);
/**
* @brief MSC information management
*/
typedef struct
{
USBH_MSC_STATE_T state;
USBH_MSC_ERR_STATE_T errState;
USBH_MSC_REQ_STATE_T preClassReqState;
USBH_MSC_REQ_STATE_T classReqState;
uint8_t maxLun;
uint8_t curLun;
uint8_t opLun;
uint32_t timer;
USBH_MSC_STORAGE_INFO_T storage[USBH_SUPPORTED_LUN_MAX];
USBH_BOT_INFO_T usbHostBOT;
} USBH_MSC_INFO_T;
extern USBH_CLASS_T USBH_MSC_CLASS;
/**@} end of group USBH_MSC_Structures*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
USBH_STA_T USBH_MSC_ReadDevInfo(USBH_INFO_T* usbInfo, uint8_t lun, USBH_MSC_STORAGE_INFO_T* device);
uint8_t USBH_MSC_DevStatus(USBH_INFO_T* usbInfo, uint8_t lun);
uint8_t USBH_MSC_ReadDevWP(USBH_INFO_T* usbInfo, uint8_t lun);
USBH_STA_T USBH_MSC_DevRead(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt);
USBH_STA_T USBH_MSC_DevWrite(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt);
/**@} end of group USBH_MSC_Functions */
/**@} end of group USBH_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,203 @@
/*!
* @file usbh_msc_bot.h
*
* @brief USB host MSC bot
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_MSC_BOT_H_
#define _USBH_MSC_BOT_H_
/* Includes */
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_MSC_Class
@{
*/
/** @defgroup USBH_MSC_Macros Macros
@{
*/
/* CBW parameter */
#define USBH_MSC_BOT_CBW_SIGNATURE (uint32_t)(0x43425355)
#define USBH_MSC_BOT_CBW_TAG (uint32_t)(0x20304050)
#define USBH_MSC_BOT_CBW_LEN 31
#define USBH_BOT_CBW_CB_LEN 16
#define USBH_LEN_CBW 10
/* CSW parameter */
#define USBH_MSC_BOT_CSW_SIGNATURE (uint32_t)(0x53425355)
#define USBH_MSC_BOT_CSW_LEN 13
#define USBH_LEN_CSW_MAX 63
/**@} end of group USBH_MSC_Macros*/
/** @defgroup USBH_MSC_Enumerates Enumerates
@{
*/
/**
* @brief SCSI transmission state of BOT
*/
typedef enum
{
USBH_BOT_SEND_CBW,
USBH_BOT_SEND_CBW_WAIT,
USBH_BOT_DATAIN,
USBH_BOT_DATAIN_WAIT,
USBH_BOT_DATAOUT,
USBH_BOT_DATAOUT_WAIT,
USBH_BOT_RECEIVE_CSW,
USBH_BOT_RECEIVE_CSW_WAIT,
USBH_BOT_ERROR_IN,
USBH_BOT_ERROR_OUT,
USBH_BOT_ERROR_UNRECOVERED,
} USBH_BOT_STATE_T;
/**
* @brief CSW status
*/
typedef enum
{
USBH_BOT_CSW_OK,
USBH_BOT_CSW_FAIL,
USBH_BOT_CSW_ERR,
} USBH_BOT_CSW_STA_T;
/**
* @brief SCSI transmission command state of BOT
*/
typedef enum
{
USBH_BOT_XFER_IDLE,
USBH_BOT_XFER_START,
USBH_BOT_XFER_WAITING,
} USBH_BOT_XFER_STA_T;
/**@} end of group USBH_MSC_Enumerates*/
/** @defgroup USBH_MSC_Structures Structures
@{
*/
/**
* @brief CBW flag
*/
typedef union
{
uint8_t CBW_Flag;
struct
{
uint8_t reserved : 7;
uint8_t dir : 1;
} CBW_FLAG_B;
} USBH_BOT_CBW_FLAG_T;
/**
* @brief Command Block Wrapper
*/
typedef union
{
struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataXferLen;
USBH_BOT_CBW_FLAG_T bmFlags;
uint8_t bLUN;
uint8_t bCBLen;
uint8_t CB[16];
} DATA_FIELD;
uint8_t buffer[31];
} USBH_BOT_CBW_T;
/**
* @brief Command Status Wrapper
*/
typedef union
{
struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataResidue;
uint8_t bStatus;
} DATA_FIELD;
uint8_t buffer[13];
} USBH_BOT_CSW_T;
/**
* @brief BOT transmission parameter
*/
typedef struct
{
USBH_BOT_CBW_T CBW;
USBH_BOT_CSW_T CSW;
} USBH_BOT_CMDPACK_T;
/* Host BOT state handler function */
typedef USBH_STA_T(*USBH_BotStateHandler_T)(struct _USBH_INFO_T* usbInfo, uint8_t lun);
/**
* @brief MSC BOT information
*/
typedef struct
{
uint8_t* buffer;
uint32_t data[16];
uint8_t inChNum;
uint8_t outChNum;
uint8_t bulkOutEpAddr;
uint8_t bulkInEpAddr;
uint16_t bulkInEpSize;
uint16_t bulkOutEpSize;
USBH_BOT_STATE_T state;
uint8_t xferState;
USBH_BOT_CMDPACK_T cmdPack;
} USBH_BOT_INFO_T;
extern USBH_BotStateHandler_T USBH_MSC_BOT_Handler[];
/**@} end of group USBH_MSC_Structures*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
USBH_STA_T USBH_MSC_BOT_Init(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_MSC_BOT_REQ_Reset(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_MSC_BOT_REQ_GetMaxLunHandler(USBH_INFO_T* usbInfo, uint8_t* maxLun);
/**@} end of group USBH_MSC_Functions */
/**@} end of group USBH_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,191 @@
/*!
* @file usbh_msc_scsi.h
*
* @brief USB host MSC scsi
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef __USBH_MSC_SCSI_H_
#define __USBH_MSC_SCSI_H_
/* Includes */
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_MSC_Class
@{
*/
/** @defgroup USBH_MSC_Macros Macros
@{
*/
/* Length define of command */
#define LEN_XFER_TEST_UNIT_READY 0
#define LEN_XFER_READ_CAPACITY 8
#define LEN_XFER_REQUEST_SENSE 14
#define LEN_XFER_INQUIRY 36
/* SCSI Commands */
#define USBH_SCSI_CMD_FORMAT_UNIT ((uint8_t)0x04)
#define USBH_SCSI_CMD_INQUIRY ((uint8_t)0x12)
#define USBH_SCSI_CMD_MODE_SELECT_6 ((uint8_t)0x15)
#define USBH_SCSI_CMD_MODE_SELECT_10 ((uint8_t)0x55)
#define USBH_SCSI_CMD_MODE_SENSE_6 ((uint8_t)0x1A)
#define USBH_SCSI_CMD_MODE_SENSE_10 ((uint8_t)0x5A)
#define USBH_SCSI_CMD_ALLOW_MEDIUM_REMOVAL ((uint8_t)0x1E)
#define USBH_SCSI_CMD_READ_6 ((uint8_t)0x08)
#define USBH_SCSI_CMD_READ_10 ((uint8_t)0x28)
#define USBH_SCSI_CMD_READ_12 ((uint8_t)0xA8)
#define USBH_SCSI_CMD_READ_16 ((uint8_t)0x88)
#define USBH_SCSI_CMD_READ_CAPACITY ((uint8_t)0x25)
#define USBH_SCSI_CMD_READ_CAPACITY_16 ((uint8_t)0x9E)
#define USBH_SCSI_CMD_REQUEST_SENSE ((uint8_t)0x03)
#define USBH_SCSI_CMD_START_STOP_UNIT ((uint8_t)0x1B)
#define USBH_SCSI_CMD_TEST_UNIT_READY ((uint8_t)0x00)
#define USBH_SCSI_CMD_WRITE6 ((uint8_t)0x0A)
#define USBH_SCSI_CMD_WRITE10 ((uint8_t)0x2A)
#define USBH_SCSI_CMD_WRITE12 ((uint8_t)0xAA)
#define USBH_SCSI_CMD_WRITE16 ((uint8_t)0x8A)
#define USBH_SCSI_CMD_VERIFY_10 ((uint8_t)0x2F)
#define USBH_SCSI_CMD_VERIFY_12 ((uint8_t)0xAF)
#define USBH_SCSI_CMD_VERIFY_16 ((uint8_t)0x8F)
#define USBH_SCSI_CMD_SEND_DIAGNOSTIC ((uint8_t)0x1D)
#define USBH_SCSI_CMD_READ_FORMAT_CAPACITIES ((uint8_t)0x23)
/**@} end of group USBH_MSC_Macros*/
/** @defgroup USBH_MSC_Enumerates Enumerates
@{
*/
/**
* @brief SCSI sense ASC type
*/
typedef enum
{
USBH_SCSI_ASC_NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
USBH_SCSI_ASCQ_FORMAT_COMMAND_FAILED = 0x01,
USBH_SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED = 0x02,
USBH_SCSI_ASC_LOGICAL_UNIT_NOT_READY = 0x04,
USBH_SCSI_ASCQ_OPERATION_IN_PROGRESS = 0x07,
USBH_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x20,
USBH_SCSI_ASC_INVALID_FIELD_IN_CDB = 0x24,
USBH_SCSI_ASC_WRITE_PROTECTED = 0x27,
USBH_SCSI_ASC_NOT_READY_TO_READY_CHANGE = 0x28,
USBH_SCSI_ASC_FORMAT_ERROR = 0x31,
USBH_SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A,
} USBH_SCSI_SENSE_ASC_T;
/**
* @brief SCSI sense key type
*/
typedef enum
{
USBH_SCSI_SENSE_KEY_NO_SENSE = 0x00,
USBH_SCSI_SENSE_KEY_RECOVERED_ERROR,
USBH_SCSI_SENSE_KEY_NOT_READY,
USBH_SCSI_SENSE_KEY_MEDIUM_ERROR,
USBH_SCSI_SENSE_KEY_HARDWARE_ERROR,
USBH_SCSI_SENSE_KEY_ILLEGAL_REQUEST,
USBH_SCSI_SENSE_KEY_UNIT_ATTENTION,
USBH_SCSI_SENSE_KEY_DATA_PROTECT,
USBH_SCSI_SENSE_KEY_BLANK_CHECK,
USBH_SCSI_SENSE_KEY_VENDOR_SPECIFIC,
USBH_SCSI_SENSE_KEY_COPY_ABORTED,
USBH_SCSI_SENSE_KEY_ABORTED_COMMAND,
USBH_SCSI_SENSE_KEY_VOLUME_OVERFLOW = 0x0D,
USBH_SCSI_SENSE_KEY_MISCOMPARE = 0x0E,
} USBH_SCSI_SENSE_KEY_T;
/**@} end of group USBH_MSC_Enumerates*/
/** @defgroup USBH_MSC_Structures Structures
@{
*/
/**
* @brief SCSI inquiry response data type
*/
typedef struct
{
uint8_t peripheral;
uint8_t devType;
uint8_t media;
uint8_t vendorID[9];
uint8_t productID[17];
uint8_t revID[5];
} USBH_SCSI_INQUIRY_REQ_T;
/**
* @brief SCSI read capacity response data type
*/
typedef struct
{
uint32_t blockNum;
uint32_t blockSize;
} USBH_SCSI_READ_CAPACITY_REQ_T;
/**
* @brief SCSI sense response data type
*/
typedef struct
{
uint8_t key;
uint8_t asc;
uint8_t ascq;
} USBH_SCSI_SENSE_REQ_T;
/**@} end of group USBH_MSC_Structures*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
USBH_STA_T USBH_MSC_SCSI_Inquiry(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_INQUIRY_REQ_T* inquiry);
USBH_STA_T USBH_MSC_SCSI_TestUnitReady(USBH_INFO_T* usbInfo, uint8_t lun);
USBH_STA_T USBH_MSC_SCSI_ReadCapacity(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_READ_CAPACITY_REQ_T* capacity);
USBH_STA_T USBH_MSC_SCSI_RequestSense(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_SENSE_REQ_T* sense);
USBH_STA_T USBH_MSC_SCSI_Read(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt);
USBH_STA_T USBH_MSC_SCSI_Write(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt);
/**@} end of group USBH_MSC_Functions */
/**@} end of group USBH_MSC_Class */
/**@} end of group APM32_USB_Library */
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,672 @@
/*!
* @file usbh_msc_bot.c
*
* @brief USB host MSC bot
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_msc_bot.h"
#include "usbh_msc.h"
#include "usbh_dataXfer.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_MSC_Class
@{
*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
static USBH_STA_T USBH_MSC_BOT_SendCBWHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_SendCBWWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_DataInHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_DataInWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_DataOutHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_DataOutWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_RevCSWHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_RevCSWWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_ErrorInHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_ErrorOutHandler(USBH_INFO_T* usbInfo, uint8_t lun);
static USBH_STA_T USBH_MSC_BOT_ErrorUnrecoveredHandler(USBH_INFO_T* usbInfo, uint8_t lun);
/**@} end of group USBH_MSC_Functions */
/** @defgroup USBH_MSC_Structures Structures
@{
*/
/* USB host BOT state handler function */
USBH_BotStateHandler_T USBH_MSC_BOT_Handler[] =
{
USBH_MSC_BOT_SendCBWHandler,
USBH_MSC_BOT_SendCBWWaitHandler,
USBH_MSC_BOT_DataInHandler,
USBH_MSC_BOT_DataInWaitHandler,
USBH_MSC_BOT_DataOutHandler,
USBH_MSC_BOT_DataOutWaitHandler,
USBH_MSC_BOT_RevCSWHandler,
USBH_MSC_BOT_RevCSWWaitHandler,
USBH_MSC_BOT_ErrorInHandler,
USBH_MSC_BOT_ErrorOutHandler,
USBH_MSC_BOT_ErrorUnrecoveredHandler,
};
/**@} end of group USBH_MSC_Structures*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
/*!
* @brief USB host MSC BOT send CBW handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval CSW decode status
*/
static USBH_BOT_CSW_STA_T USBH_MSC_BOT_DecodeCSW(USBH_INFO_T* usbInfo)
{
USBH_BOT_CSW_STA_T cswStatus = USBH_BOT_CSW_FAIL;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
uint32_t lastXferSize;
lastXferSize = USBH_ReadLastXferSizeCallback(usbInfo, usbHostMSC->usbHostBOT.inChNum);
/* CSW length is Correct */
if (lastXferSize == USBH_MSC_BOT_CSW_LEN)
{
/* dSignature is equal to 0x53425355 */
if (usbHostMSC->usbHostBOT.cmdPack.CSW.DATA_FIELD.dSignature == USBH_MSC_BOT_CSW_SIGNATURE)
{
/* dTag matches the dTag from the corresponding CBW */
if (usbHostMSC->usbHostBOT.cmdPack.CSW.DATA_FIELD.dTag == usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dTag)
{
switch (usbHostMSC->usbHostBOT.cmdPack.CSW.DATA_FIELD.bStatus)
{
case USBH_BOT_CSW_OK:
cswStatus = USBH_BOT_CSW_OK;
break;
case USBH_BOT_CSW_FAIL:
cswStatus = USBH_BOT_CSW_FAIL;
break;
case USBH_BOT_CSW_ERR:
cswStatus = USBH_BOT_CSW_ERR;
break;
}
}
}
else
{
cswStatus = USBH_BOT_CSW_ERR;
}
}
else
{
cswStatus = USBH_BOT_CSW_ERR;
}
return cswStatus;
}
/*!
* @brief USB host MSC BOT send CBW handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_SendCBWHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bLUN = lun;
USBH_USR_Debug("USBH_MSC_BOT_SendCBWHandler");
USBH_BulkSendDataReq(usbInfo, usbHostMSC->usbHostBOT.outChNum, usbHostMSC->usbHostBOT.cmdPack.CBW.buffer, \
USBH_MSC_BOT_CBW_LEN, ENABLE);
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW_WAIT;
return usbStatus;
}
/*!
* @brief USB host MSC BOT send CBW wait handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_SendCBWWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_SendCBWWaitHandler");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbHostMSC->usbHostBOT.outChNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen == 0)
{
usbHostMSC->usbHostBOT.state = USBH_BOT_RECEIVE_CSW;
}
else
{
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir == USBH_REQ_DIR_IN)
{
usbHostMSC->usbHostBOT.state = USBH_BOT_DATAIN;
}
else
{
usbHostMSC->usbHostBOT.state = USBH_BOT_DATAOUT;
}
}
break;
case USB_URB_NOREADY:
/* Resend CBW */
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
break;
case USB_URB_STALL:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_OUT;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT data IN handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_DataInHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_DataInHandler");
USBH_BulkReceiveDataReq(usbInfo, usbHostMSC->usbHostBOT.inChNum, usbHostMSC->usbHostBOT.buffer, \
usbHostMSC->usbHostBOT.bulkInEpSize);
usbHostMSC->usbHostBOT.state = USBH_BOT_DATAIN_WAIT;
return usbStatus;
}
/*!
* @brief USB host MSC BOT data IN wait handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_DataInWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_DataInWaitHandler");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbHostMSC->usbHostBOT.inChNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen <= usbHostMSC->usbHostBOT.bulkInEpSize)
{
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = 0;
}
else
{
usbHostMSC->usbHostBOT.buffer += usbHostMSC->usbHostBOT.bulkInEpSize;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen -= usbHostMSC->usbHostBOT.bulkInEpSize;
}
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen > 0)
{
/* Receive the next bulk packet */
USBH_BulkReceiveDataReq(usbInfo, usbHostMSC->usbHostBOT.inChNum, usbHostMSC->usbHostBOT.buffer, \
usbHostMSC->usbHostBOT.bulkInEpSize);
}
else
{
usbHostMSC->usbHostBOT.state = USBH_BOT_RECEIVE_CSW;
}
break;
case USB_URB_STALL:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_IN;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT data OUT handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_DataOutHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_DataOutHandler");
USBH_BulkSendDataReq(usbInfo, usbHostMSC->usbHostBOT.outChNum, usbHostMSC->usbHostBOT.buffer, \
usbHostMSC->usbHostBOT.bulkOutEpSize, ENABLE);
usbHostMSC->usbHostBOT.state = USBH_BOT_DATAOUT_WAIT;
return usbStatus;
}
/*!
* @brief USB host MSC BOT data OUT wait handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_DataOutWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_DataOutWaitHandler");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbHostMSC->usbHostBOT.outChNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen <= usbHostMSC->usbHostBOT.bulkOutEpSize)
{
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = 0;
}
else
{
usbHostMSC->usbHostBOT.buffer += usbHostMSC->usbHostBOT.bulkOutEpSize;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen -= usbHostMSC->usbHostBOT.bulkOutEpSize;
}
if (usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen > 0)
{
/* Send the next bulk packet */
USBH_BulkSendDataReq(usbInfo, usbHostMSC->usbHostBOT.outChNum, usbHostMSC->usbHostBOT.buffer, \
usbHostMSC->usbHostBOT.bulkOutEpSize, ENABLE);
}
else
{
usbHostMSC->usbHostBOT.state = USBH_BOT_RECEIVE_CSW;
}
break;
case USB_URB_NOREADY:
usbHostMSC->usbHostBOT.state = USBH_BOT_DATAOUT;
break;
case USB_URB_STALL:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_OUT;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT receive CSW handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_RevCSWHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_RevCSWHandler");
USBH_BulkReceiveDataReq(usbInfo, usbHostMSC->usbHostBOT.inChNum, usbHostMSC->usbHostBOT.cmdPack.CSW.buffer, \
USBH_MSC_BOT_CSW_LEN);
usbHostMSC->usbHostBOT.state = USBH_BOT_RECEIVE_CSW_WAIT;
return usbStatus;
}
/*!
* @brief USB host MSC BOT reveive CSW wait handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_RevCSWWaitHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_BOT_CSW_STA_T cswStatus = USBH_BOT_CSW_FAIL;
USBH_USR_Debug("USBH_MSC_BOT_RevCSWWaitHandler");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbHostMSC->usbHostBOT.inChNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_START;
cswStatus = USBH_MSC_BOT_DecodeCSW(usbInfo);
if (cswStatus == USBH_BOT_CSW_OK)
{
usbStatus = USBH_OK;
}
else
{
usbStatus = USBH_FAIL;
}
break;
case USB_URB_STALL:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_IN;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT IN error handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_ErrorInHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t reqStatus = USBH_OK;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_ErrorInHandler");
reqStatus = USBH_ClearFeature(usbInfo, usbHostMSC->usbHostBOT.bulkInEpAddr);
switch (reqStatus)
{
case USBH_OK:
usbHostMSC->usbHostBOT.state = USBH_BOT_RECEIVE_CSW;
break;
case USBH_ERR_UNRECOVERED:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_UNRECOVERED;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT OUT error handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_ErrorOutHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t reqStatus = USBH_OK;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
uint8_t toggle;
USBH_USR_Debug("USBH_MSC_BOT_ErrorOutHandler");
reqStatus = USBH_ClearFeature(usbInfo, usbHostMSC->usbHostBOT.bulkOutEpAddr);
switch (reqStatus)
{
case USBH_OK:
toggle = USBH_ReadToggleCallback(usbInfo, usbHostMSC->usbHostBOT.outChNum);
USBH_ConfigToggleCallback(usbInfo, usbHostMSC->usbHostBOT.outChNum, 1 - toggle);
USBH_ConfigToggleCallback(usbInfo, usbHostMSC->usbHostBOT.inChNum, 0);
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_IN;
break;
case USBH_ERR_UNRECOVERED:
usbHostMSC->usbHostBOT.state = USBH_BOT_ERROR_UNRECOVERED;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC BOT unrecovered error handler
*
* @param usbInfo : usb handler information
*
* @param lun : logical unit numer
*
* @retval USB host operation status
*/
static USBH_STA_T USBH_MSC_BOT_ErrorUnrecoveredHandler(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t reqStatus = USBH_OK;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
USBH_USR_Debug("USBH_MSC_BOT_ErrorUnrecoveredHandler");
reqStatus = USBH_MSC_BOT_REQ_Reset(usbInfo);
switch (reqStatus)
{
case USBH_OK:
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief Init BOT of USB host MSC
*
* @param usbInfo : usb handler information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_BOT_Init(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dSignature = USBH_MSC_BOT_CBW_SIGNATURE;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dTag = USBH_MSC_BOT_CBW_TAG;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_START;
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
return usbStatus;
}
/*!
* @brief Reset request of MSC BOT
*
* @param usbInfo : usb handler information
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_BOT_REQ_Reset(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
/* Config Request */
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = USBH_REQ_DIR_OUT;
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = USBH_RECIPIENT_INTERFACE;
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = USBH_REQ_TYPE_CLASS;
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_CLASS_BOT_RESET;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0x00;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief Get the max lun of MSC BOT
*
* @param usbInfo : usb handler information
*
* @param maxLun: max of logic unit number
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_BOT_REQ_GetMaxLunHandler(USBH_INFO_T* usbInfo, uint8_t* maxLun)
{
USBH_STA_T usbStatus = USBH_OK;
/* Config Request */
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = USBH_REQ_DIR_IN;
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = USBH_RECIPIENT_INTERFACE;
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = USBH_REQ_TYPE_CLASS;
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_CLASS_GET_MAX_LUN;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0x00;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0x01;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0x00;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, maxLun, 1);
return usbStatus;
}
/**@} end of group USBH_MSC_Functions */
/**@} end of group USBH_MSC_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,395 @@
/*!
* @file usbh_msc_scsi.c
*
* @brief USB host MSC scsi
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_msc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_MSC_Class
@{
*/
/** @defgroup USBH_MSC_Functions Functions
@{
*/
/*!
* @brief USB host MSC SCSI INQUIRY handler
*
* @param usbInfo
*
* @param lun: logical unit number
*
* @param inquiry: inquiry response
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_Inquiry(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_INQUIRY_REQ_T* inquiry)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = LEN_XFER_INQUIRY;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_IN;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_INQUIRY;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[1] = (lun << 5);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[2] = 0;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[3] = 0;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[4] = 36;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[5] = 0;
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
/* Init buffer point */
usbHostMSC->usbHostBOT.buffer = (uint8_t*)(void*)usbHostMSC->usbHostBOT.data;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
switch (usbStatus)
{
case USBH_OK:
memset(inquiry, 0, sizeof(USBH_SCSI_INQUIRY_REQ_T));
inquiry->devType = usbHostMSC->usbHostBOT.buffer[0] & 0x1F;
inquiry->peripheral = usbHostMSC->usbHostBOT.buffer[0] >> 5;
if (((uint32_t) usbHostMSC->usbHostBOT.buffer[1] & 0x80) == 0x80)
{
inquiry->media = 1;
}
else
{
inquiry->media = 0;
}
memcpy(inquiry->revID, &usbHostMSC->usbHostBOT.buffer[32], 4);
memcpy(inquiry->productID, &usbHostMSC->usbHostBOT.buffer[16], 16);
memcpy(inquiry->vendorID, &usbHostMSC->usbHostBOT.buffer[8], 8);
break;
default:
break;
}
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC SCSI TEST UNIT READY handler
*
* @param usbInfo
*
* @param lun: logical unit number
*
* @param inquiry: inquiry response
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_TestUnitReady(USBH_INFO_T* usbInfo, uint8_t lun)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbStatus = USBH_BUSY;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = LEN_XFER_TEST_UNIT_READY;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_OUT;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_TEST_UNIT_READY;
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC SCSI READ CAPACITY handler
*
* @param usbInfo
*
* @param lun: logical unit number
*
* @param capacity: capacity response
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_ReadCapacity(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_READ_CAPACITY_REQ_T* capacity)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = LEN_XFER_READ_CAPACITY;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_IN;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_READ_CAPACITY;
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
/* Init buffer point */
usbHostMSC->usbHostBOT.buffer = (uint8_t*)(void*)usbHostMSC->usbHostBOT.data;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
switch (usbStatus)
{
case USBH_OK:
capacity->blockNum = usbHostMSC->usbHostBOT.buffer[3] | (usbHostMSC->usbHostBOT.buffer[2] << 8) | \
(usbHostMSC->usbHostBOT.buffer[1] << 16) | (usbHostMSC->usbHostBOT.buffer[0] << 24);
capacity->blockSize = usbHostMSC->usbHostBOT.buffer[7] | (usbHostMSC->usbHostBOT.buffer[6] << 8) | \
(usbHostMSC->usbHostBOT.buffer[5] << 16) | (usbHostMSC->usbHostBOT.buffer[4] << 24);
break;
default:
break;
}
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC SCSI request sense handler
*
* @param usbInfo
*
* @param lun: logical unit number
*
* @param sense: sense response
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_RequestSense(USBH_INFO_T* usbInfo, uint8_t lun, \
USBH_SCSI_SENSE_REQ_T* sense)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = LEN_XFER_REQUEST_SENSE;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_IN;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_REQUEST_SENSE;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[1] = (lun << 5);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[2] = 0;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[3] = 0;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[4] = LEN_XFER_REQUEST_SENSE;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[5] = 0;
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
/* Init buffer point */
usbHostMSC->usbHostBOT.buffer = (uint8_t*)(void*)usbHostMSC->usbHostBOT.data;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
switch (usbStatus)
{
case USBH_OK:
sense->key = usbHostMSC->usbHostBOT.buffer[2] & 0x0F;
sense->asc = usbHostMSC->usbHostBOT.buffer[12];
sense->ascq = usbHostMSC->usbHostBOT.buffer[13];
break;
default:
break;
}
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC SCSI read10 handler
*
* @param usbInfo: usb host information
*
* @param lun: logical unit number
*
* @param address: sector address
*
* @param buffer: buffer point to data
*
* @param cnt: count number of data
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_Read(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = cnt * usbHostMSC->storage[0].capacity.blockSize;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_IN;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_READ_10;
/* logical block address*/
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[2] = (((uint8_t*)&address)[3]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[3] = (((uint8_t*)&address)[2]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[4] = (((uint8_t*)&address)[1]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[5] = (((uint8_t*)&address)[0]);
/* Transfer length */
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[7] = (((uint8_t*)&cnt)[1]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[8] = (((uint8_t*)&cnt)[0]);
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
/* Init buffer point */
usbHostMSC->usbHostBOT.buffer = buffer;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
break;
}
return usbStatus;
}
/*!
* @brief USB host MSC SCSI write10 handler
*
* @param usbInfo: usb host information
*
* @param lun: logical unit number
*
* @param address: sector address
*
* @param buffer: buffer point to data
*
* @param cnt: count number of data
*
* @retval USB host operation status
*/
USBH_STA_T USBH_MSC_SCSI_Write(USBH_INFO_T* usbInfo, uint8_t lun, uint32_t address, \
uint8_t* buffer, uint16_t cnt)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_MSC_INFO_T* usbHostMSC = (USBH_MSC_INFO_T*)usbInfo->activeClass->classData;
switch (usbHostMSC->usbHostBOT.xferState)
{
case USBH_BOT_XFER_START:
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.dDataXferLen = cnt * usbHostMSC->storage[0].capacity.blockSize;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bmFlags.CBW_FLAG_B.dir = USBH_REQ_DIR_OUT;
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.bCBLen = USBH_LEN_CBW;
memset(usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB, 0, USBH_BOT_CBW_CB_LEN);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[0] = USBH_SCSI_CMD_WRITE10;
/* logical block address*/
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[2] = (((uint8_t*)&address)[3]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[3] = (((uint8_t*)&address)[2]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[4] = (((uint8_t*)&address)[1]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[5] = (((uint8_t*)&address)[0]);
/* Transfer length */
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[7] = (((uint8_t*)&cnt)[1]);
usbHostMSC->usbHostBOT.cmdPack.CBW.DATA_FIELD.CB[8] = (((uint8_t*)&cnt)[0]);
usbHostMSC->usbHostBOT.state = USBH_BOT_SEND_CBW;
usbHostMSC->usbHostBOT.xferState = USBH_BOT_XFER_WAITING;
/* Init buffer point */
usbHostMSC->usbHostBOT.buffer = buffer;
break;
case USBH_BOT_XFER_WAITING:
usbStatus = USBH_MSC_BOT_Handler[usbHostMSC->usbHostBOT.state](usbInfo, lun);
break;
}
return usbStatus;
}
/**@} end of group USBH_MSC_Functions */
/**@} end of group USBH_MSC_Class */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,53 @@
/*!
* @file usbh_channel.h
*
* @brief USB host channel handler function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_CHANNEL_H_
#define _USBH_CHANNEL_H_
/* Includes */
#include "usbh_config.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
void USBH_CH_Clear(USBH_INFO_T* usbInfo);
void USBH_CH_FreeChannel(USBH_INFO_T* usbInfo, uint8_t chNum);
uint8_t USBH_CH_AllocChannel(USBH_INFO_T* usbInfo, uint8_t epAddr);
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,491 @@
/*!
* @file usbh_config.h
*
* @brief usb host config header file
*
* @version V1.0.1
*
* @date 2023-03-27
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_CONFIG_H_
#define _USBH_CONFIG_H_
/* Includes */
#include "usbh_board.h"
#include <stdio.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Macros Macros
@{
*/
/*!< [31:16] APM32 USB Host Library main version V1.1.3*/
#define __APM32_USB_HOST_VERSION_MAIN (0x01) /*!< [31:24] main version */
#define __APM32_USB_HOST_VERSION_SUB1 (0x01) /*!< [23:16] sub1 version */
#define __APM32_USB_HOST_VERSION_SUB2 (0x03) /*!< [15:8] sub2 version */
#define __APM32_USB_HOST_VERSION_RC (0x00) /*!< [7:0] release candidate */
#define __APM32_USB_HOST_VERSION ((__APM32_USB_HOST_VERSION_MAIN << 24)\
|(__APM32_USB_HOST_VERSION_SUB1 << 16)\
|(__APM32_USB_HOST_VERSION_SUB2 << 8 )\
|(__APM32_USB_HOST_VERSION_RC))
#define USBH_EP0_PACKET_SIZE 0x40
#define USBH_LANG_ID 0x0409
#define USB_REQ_DIR_OUT 0x00
#define USB_REQ_DIR_IN 0x80
#define USBH_DEVICE_RESET_TIMEOUT 0x64
#define USBH_DEVICE_DEFAULT_ADDRESS 0
#define USBH_DEVICE_CONFIGURED_ADDRESS 1
#define STD_DEV_DESC_SIZE 18
#define STD_CFG_DESC_SIZE 9
#define STD_INTERFACE_DESC_SIZE 9
#define STD_EP_DESC_SIZE 7
#define STD_HID_DESC_SIZE 9
#define CFG_DESC_MAX_LEN 256
#define STRING_DESC_MAX_LEN 0x200
#ifndef USBH_Delay
#define USBH_Delay DAL_Delay
#endif
/**@} end of group USBH_Core_Macros*/
/** @defgroup USBH_Core_Enumerates Enumerates
@{
*/
/**
* @brief USB host speed type
*/
typedef enum
{
USBH_SPEED_FS,
USBH_SPEED_HS,
} USBH_SPEED_T;
/**
* @brief USB device speed
*/
typedef enum
{
USBH_DEVICE_SPEED_HS,
USBH_DEVICE_SPEED_FS,
USBH_DEVICE_SPEED_LS
} USBH_DEVICE_SPEED_T;
/**
* @brief USB host operation status
*/
typedef enum
{
USBH_OK,
USBH_BUSY,
USBH_FAIL,
USBH_ERR_NOT_SUP,
USBH_ERR_UNRECOVERED,
USBH_ERR_SPEED_UNKOWN,
} USBH_STA_T;
/**
* @brief USB host state machine
*/
typedef enum
{
USBH_HOST_IDLE,
USBH_HOST_DEVICE_ATTACHED,
USBH_HOST_DEVICE_DISCONNECTED,
USBH_HOST_ENUMERATION,
USBH_HOST_CLASS_REQ,
USBH_HOST_USER_INPUT,
USBH_HOST_SET_CONFIGURATION,
USBH_HOST_SET_FEATURE,
USBH_HOST_CLASS_ACTIVE,
USBH_HOST_CLASS,
USBH_HOST_SUSPEND,
USBH_HOST_ABORT,
} USBH_HOST_STA_T;
/**
* @brief USB host enumeration state
*/
typedef enum
{
USBH_ENUM_IDLE, //!< enum idle
USBH_ENUM_GET_DEV_DESC, //!< Get device descriptor
USBH_ENUM_SET_ADDR, //!< Set address
USBH_ENUM_GET_CFG_DESC, //!< Get Configuration descriptor
USBH_ENUM_GET_FULL_CFG_DESC, //!< Get Full Configuration descriptor
USBH_ENUM_GET_MFC_STRING_DESC, //!< Get Manufacturer string
USBH_ENUM_GET_PRODUCT_STRING_DESC, //!< Get Product string
USBH_ENUM_GET_SERIALNUM_STRING_DESC, //!< Get serial number string
} USBH_ENUM_STA_T;
/**
* @brief USB transfer state
*/
typedef enum
{
USBH_XFER_START,
USBH_XFER_WAITING,
USBH_XFER_OK,
} USBH_XFER_STA_T;
/**
* @brief USB Host control transfer state
*/
typedef enum
{
USBH_CTRL_IDLE,
USBH_CTRL_SETUP,
USBH_CTRL_SETUP_WAIT,
USBH_CTRL_DATA_IN,
USBH_CTRL_DATA_IN_WAIT,
USBH_CTRL_DATA_OUT,
USBH_CTRL_DATA_OUT_WAIT,
USBH_CTRL_STA_IN,
USBH_CTRL_STA_IN_WAIT,
USBH_CTRL_STA_OUT,
USBH_CTRL_STA_OUT_WAIT,
USBH_CTRL_ERROR,
USBH_CTRL_STALL,
USBH_CTRL_OK
} USBH_CTRL_STATE_T;
/**
* @brief USB device feature request type
*/
typedef enum
{
USBH_FEATURE_SELECTOR_ENDPOINT_HALT,
USBH_FEATURE_REMOTE_WAKEUP,
USBH_FEATURE_TEST_MODE,
} USBH_REQ_FEATURE_T;
/**
* @brief USB device request direction
*/
typedef enum
{
USBH_REQ_DIR_OUT,
USBH_REQ_DIR_IN
} USBH_DEV_REQ_DIR_T;
/**
* @brief USB device request type
*/
typedef enum
{
USBH_REQ_TYPE_STANDARD = 0,
USBH_REQ_TYPE_CLASS,
USBH_REQ_TYPE_VENDOR,
USBH_REQ_TYPE_RESERVED
} USBH_DEV_REQ_TYPE_T;
/**
* @brief USB device request recipient
*/
typedef enum
{
USBH_RECIPIENT_DEVICE = 0,
USBH_RECIPIENT_INTERFACE,
USBH_RECIPIENT_ENDPOINT,
USBH_RECIPIENT_OTHER
} USBH_DEV_RECIPIENT_T;
/**
* @brief USB standard device standard requests type
*/
typedef enum
{
USBH_STD_GET_STATUS = 0,
USBH_STD_CLEAR_FEATURE = 1,
USBH_STD_SET_FEATURE = 3,
USBH_STD_SET_ADDRESS = 5,
USBH_STD_GET_DESCRIPTOR = 6,
USBH_STD_SET_DESCRIPTOR = 7,
USBH_STD_GET_CONFIGURATION = 8,
USBH_STD_SET_CONFIGURATION = 9,
USBH_STD_GET_INTERFACE = 10,
USBH_STD_SET_INTERFACE = 11,
USBH_STD_SYNCH_FRAME = 12
} USBH_STD_REQ_TYPE_T;
/**
* @brief USB descriptor types
*/
typedef enum
{
USBH_DESC_DEVICE = 1,
USBH_DESC_CONFIGURATION = 2,
USBH_DESC_STRING = 3,
USBH_DESC_INTERFACE = 4,
USBH_DESC_ENDPOINT = 5,
USBH_DESC_DEVICE_QUALIFIER = 6,
USBH_DESC_OTHER_SPEED = 7,
USBH_DESC_INTERFACE_POWER = 8,
USBH_DESC_HID = 0x21,
USBH_DESC_HID_REPORT = 0x22,
USBH_DESC_HID_PHY = 0x23,
} USBH_DESC_TYPE_T;
/**
* @brief USB Class type
*/
typedef enum
{
USBH_CLASS_AUDIO = 0x01, //!< Audio
USBH_CLASS_CDCC = 0x02, //!< Communications and CDC Control
USBH_CLASS_HID = 0x03, //!< HID (Human Interface Device)
USBH_CLASS_PRINTER = 0x07, //!< Printer
USBH_CLASS_MSC = 0x08, //!< Mass Storage
USBH_CLASS_HUB = 0x09, //!< Hub
USBH_CLASS_CDCD = 0x0A, //!< CDC-Data
USBH_CLASS_SMARTCARD = 0x0B, //!< Smart Card
USBH_CLASS_VIDEO = 0x0E, //!< Video
USBH_CLASS_AVD = 0x10 //!< Audio/Video Devices
} USBH_CLASS_TYPE_T;
/**@} end of group USBH_Core_Enumerates*/
/** @defgroup USBH_Core_Structures Structures
@{
*/
/**
* @brief USB request type
*/
typedef union
{
uint8_t REQ_TYPE;
struct
{
uint8_t recipient : 5;
uint8_t type : 2;
uint8_t dir : 1;
} REQ_TYPE_B;
} USBH_REQ_TYPE_T;
/**
* @brief USB Host request data
*/
typedef struct
{
union
{
uint8_t REQ_DATA[8];
struct
{
USBH_REQ_TYPE_T bmRequestType;
uint8_t bRequest;
uint8_t wValue[2];
uint8_t wIndex[2];
uint8_t wLength[2];
} DATA_FIELD;
};
} USBH_REQ_DATA_T;
/**
* @brief USB device descriptor
*/
typedef struct
{
uint8_t bLength; //!< Descriptor length
uint8_t bDescriptorType; //!< Descriptor Type
uint8_t bcdUSB[2]; //!< BCD of the supported USB specification
uint8_t bDeviceClass; //!< USB device class
uint8_t bDeviceSubClass; //!< USB device subclass
uint8_t bDeviceProtocol; //!< USB device protocol
uint8_t bMaxPacketSize; //!< Max Packet Size
uint8_t idVendor[2]; //!< Vendor ID
uint8_t idProduct[2]; //!< Product ID
uint8_t bcdDevice[2]; //!< Device Release Number
uint8_t iManufacturer; //!< Index of Manufacturer String Descriptor
uint8_t iProduct; //!< Index of Product String Descriptor
uint8_t iSerialNumber; //!< Index of Serial Number String Descriptor
uint8_t bNumConfigurations; //!< Number of Possible Configurations
} USBH_DEV_DESC_T;
/**
* @brief USB Endpoint descriptor
*/
typedef struct
{
uint8_t bLength; //!< Descriptor length
uint8_t bDescriptorType; //!< Descriptor Type
uint8_t bEndpointAddress; //!< Indicates what endpoint this descriptor is describing
uint8_t bmAttributes; //!< Specifies the transfer type
uint8_t wMaxPacketSize[2]; //!< Maximum Packet Size this endpoint is capable of sending or receiving
uint8_t bInterval; //!< Polling interval in milliseconds for the endpoint
} USBH_EP_DESC_T;
/**
* @brief USB Interface descriptor
*/
typedef struct
{
uint8_t bLength; //!< Descriptor length
uint8_t bDescriptorType; //!< Descriptor Type
uint8_t bInterfaceNumber; //!< Interface Number
uint8_t bAlternateSetting; //!< Value used to select alternative setting
uint8_t bNumEndpoints; //!< Number of Endpoints used for this interface
uint8_t bInterfaceClass; //!< Class Code
uint8_t bInterfaceSubClass; //!< Sub class Code
uint8_t bInterfaceProtocol; //!< Protocol Code
uint8_t iInterface; //!< Index of String Descriptor of this interface
} USBH_ITF_DESC_T;
/**
* @brief USB Configuration descriptor
*/
typedef struct
{
uint8_t bLength; //!< Descriptor length
uint8_t bDescriptorType; //!< Descriptor Type
uint8_t wTotalLength[2]; //!< Total Length of Configuration Descriptor gather
uint8_t bNumInterfaces; //!< Total number of interfaces in the configuration
uint8_t bConfigurationValue; //!< Configuration index of the current configuration
uint8_t iConfiguration; //!< Index of a string descriptor describing the configuration
uint8_t bmAttributes; //!< Configuration attributes
uint8_t bMaxPower; //!< Maximum power consumption
} USBH_CFG_DESC_T;
/**
* @brief USB Interface and Endpoint descriptor
*/
typedef struct
{
USBH_ITF_DESC_T interfaceDesc;
USBH_EP_DESC_T endpointDesc[ENDPOINT_DESC_MAX_NUM];
} USBH_INTERFACE_T;
/**
* @brief USB Host Descriptor structure
*/
typedef struct
{
USBH_DEV_DESC_T device;
USBH_CFG_DESC_T configuration;
USBH_INTERFACE_T interface[INTERFACE_DESC_MAX_NUM];
uint8_t cfgDescBuf[CFG_DESC_MAX_LEN];
uint8_t stringBuf[STRING_DESC_MAX_LEN];
} USBH_DESC_T;
/**
* @brief USB Host device information
*/
typedef struct
{
uint8_t data[USBH_DATA_BUF_MAX_NUM];
uint8_t address;
uint8_t speed;
__IO uint8_t connectedStatus;
__IO uint8_t disconnectedStatus;
__IO uint8_t reEnumStatus;
uint8_t portEnable;
uint8_t rstCnt;
uint8_t enumCnt;
USBH_DESC_T desc;
} USBH_DEV_INFO_T;
/**
* @brief USB Control thansfer info
*/
typedef struct
{
uint8_t state;
uint8_t errCnt;
uint8_t channelInNum;
uint8_t channelOutNum;
uint8_t channelSize;
uint8_t* buffer;
uint16_t length;
USBH_REQ_DATA_T reqData;
} USBH_CTRL_T;
struct _USBH_INFO_T;
/* Class callback function type define */
typedef USBH_STA_T(*USBH_ClassCallback_T)(struct _USBH_INFO_T* usbInfo);
/**
* @brief USB host class handler
*/
typedef struct
{
const char* className;
uint8_t classCode;
void* classData;
USBH_ClassCallback_T classInitHandler;
USBH_ClassCallback_T classDeInitHandler;
USBH_ClassCallback_T classReqHandler;
USBH_ClassCallback_T classCoreHandler;
USBH_ClassCallback_T classSofHandler;
} USBH_CLASS_T;
/* Host state handler function */
typedef USBH_STA_T(*USBH_CoreHandler_T)(struct _USBH_INFO_T* usbInfo);
/* Host enum state handler function */
typedef USBH_STA_T(*USBH_EnumHandler_T)(struct _USBH_INFO_T* usbInfo);
/* Host control transfer state handler function */
typedef USBH_STA_T(*USBH_CtrlStateHandler_T)(struct _USBH_INFO_T* usbInfo);
/**
* @brief USB host information
*/
typedef struct _USBH_INFO_T
{
USBH_HOST_STA_T hostState; /*!< USB Host State Machine*/
USBH_ENUM_STA_T hostEnumState;
USBH_SPEED_T hostSpeed;
USBH_DEV_INFO_T devInfo;
uint8_t xferState;
USBH_CTRL_T ctrl; /*!< Control Thansfer info management*/
USBH_CLASS_T* hostClass[USBH_SUP_CLASS_MAX_NUM]; /*!< USB host class */
USBH_CLASS_T* activeClass;
uint32_t classNum;
__IO uint32_t timer;
uint32_t timeout;
uint32_t xferChannel[USBH_CHANNEL_MAX_NUM]; /*!< Thansfer data management (The sixteenth bit is indicate free or not status)*/
void (*userCallback)(struct _USBH_INFO_T* usbInfo, uint8_t userStatus);
void* dataPoint;
} USBH_INFO_T;
/**@} end of group USBH_Core_Structures*/
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,104 @@
/*!
* @file usbh_core.h
*
* @brief USB host core function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_CORE_H_
#define _USBH_CORE_H_
/* Includes */
#include "usbh_config.h"
#include "usbh_channel.h"
#include "usbh_stdReq.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Enumerates Enumerates
@{
*/
/**
* @brief USB host user status
*/
typedef enum
{
USBH_USER_CONNECTION = 1,
USBH_USER_DISCONNECTION,
USBH_USER_DETECTED_SPEED,
USBH_USER_ENUMERATION,
USBH_USER_CLASS_LAUNCHED,
USBH_USER_NOT_SUPPORT,
USBH_USER_ERROR,
} USBH_USER_STATUS;
/**@} end of group USBH_Core_Enumerates*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
USBH_STA_T USBH_Init(USBH_INFO_T* usbInfo, USBH_SPEED_T usbHostSpeed, USBH_CLASS_T* usbHostClass,
void (*userCallbackFunc)(struct _USBH_INFO_T*, uint8_t));
USBH_STA_T USBH_DeInit(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_RegisterClass(USBH_INFO_T* usbInfo, USBH_CLASS_T* usbHostClass);
USBH_STA_T USBH_PollingProcess(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_Disconnect(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_Connect(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_PortEnable(USBH_INFO_T* usbInfo);
USBH_STA_T USBH_PortDisable(USBH_INFO_T* usbInfo);
void USBH_IncTimer(USBH_INFO_T* usbInfo);
void USBH_ConfigTimer(USBH_INFO_T* usbInfo, uint32_t tick);
void USBH_HardwareInit(USBH_INFO_T* usbInfo);
void USBH_HardwareReset(USBH_INFO_T* usbInfo);
void USBH_StopHostCallback(USBH_INFO_T* usbInfo);
void USBH_StartCallback(USBH_INFO_T* usbInfo);
void USBH_StopCallback(USBH_INFO_T* usbInfo);
void USBH_ResetCallback(USBH_INFO_T* usbInfo);
uint8_t USBH_ReadSpeedCallback(USBH_INFO_T* usbInfo);
void USBH_OpenChannelCallback(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t endPointNum, uint8_t devAddr, \
uint8_t devSpeed, uint8_t epType, uint16_t packetMaxSize);
void USBH_UrbSubmitCallback(USBH_INFO_T* usbInfo, uint8_t chNum, uint8_t dir, \
uint8_t epType, uint8_t tokenType, uint8_t* buffer, \
uint16_t length, uint8_t pingStatus);
uint8_t USBH_ReadUrbStatusCallback(USBH_INFO_T* usbInfo, uint8_t channelNum);
void USBH_ConfigDataPidCallback(USBH_INFO_T* usbInfo, uint8_t channelNum, uint8_t dataPid);
void USBH_CloseChannelCallback(USBH_INFO_T* usbInfo, uint8_t channelNum);
uint32_t USBH_ReadLastXferSizeCallback(USBH_INFO_T* usbInfo, uint8_t channelNum);
uint8_t USBH_ReadToggleCallback(USBH_INFO_T* usbInfo, uint8_t channelNum);
void USBH_ConfigToggleCallback(USBH_INFO_T* usbInfo, uint8_t channelNum, uint8_t toggle);
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,76 @@
/*!
* @file usbh_dataXfer.h
*
* @brief USB host input and output hander function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_DATAXFER_H_
#define _USBH_DATAXFER_H_
/* Includes */
#include "usbh_config.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Structures Structures
@{
*/
extern USBH_CtrlStateHandler_T USBH_CtrlStateHandler[];
/**@} end of group USBH_Core_Structures*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
USBH_STA_T USBH_BulkSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length, \
uint8_t pingStatus);
USBH_STA_T USBH_BulkReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length);
USBH_STA_T USBH_IntSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length);
USBH_STA_T USBH_IntReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length);
USBH_STA_T USBH_IntSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length);
USBH_STA_T USBH_IsoReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length);
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,51 @@
/*!
* @file usbh_enum.h
*
* @brief USB host enum hander function head file
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_ENUM_H_
#define _USBH_ENUM_H_
/* Includes */
#include "usbh_config.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Structures Structures
@{
*/
extern USBH_EnumHandler_T USBH_EnumHandler[];
/**@} end of group USBH_Core_Structures*/
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,96 @@
/*!
* @file usbh_stdReq.h
*
* @brief USB standard request process
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBH_STDREQ_H_
#define _USBH_STDREQ_H_
/* Includes */
#include "usbh_config.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Macros Macros
@{
*/
#define USBH_SETUP_PACKET_SIZE 8
#define USBH_ReadConfigurationItfNum(usbInfo) \
usbInfo->devInfo.desc.configuration.bNumInterfaces
#define USBH_ReadInterfaceClass(usbInfo, itfIndex) \
usbInfo->devInfo.desc.interface[itfIndex].interfaceDesc.bInterfaceClass
#define USBH_ReadInterfaceSubClass(usbInfo, itfIndex) \
usbInfo->devInfo.desc.interface[itfIndex].interfaceDesc.bInterfaceSubClass
#define USBH_ReadInterfaceProtocol(usbInfo, itfIndex) \
usbInfo->devInfo.desc.interface[itfIndex].interfaceDesc.bInterfaceProtocol
#define USBH_ReadInterfaceEpNum(usbInfo, itfIndex) \
usbInfo->devInfo.desc.interface[itfIndex].interfaceDesc.bNumEndpoints
#define USBH_ReadEndpointAddress(usbInfo, itfIndex, epIndex) \
usbInfo->devInfo.desc.interface[itfIndex].endpointDesc[epIndex].bEndpointAddress
#define USBH_ReadEndpointMPS(usbInfo, itfIndex, epIndex) \
((uint16_t)usbInfo->devInfo.desc.interface[itfIndex].endpointDesc[epIndex].wMaxPacketSize[0] | \
(uint16_t)usbInfo->devInfo.desc.interface[itfIndex].endpointDesc[epIndex].wMaxPacketSize[1] << 8)
#define USBH_ReadEndpointInterval(usbInfo, itfIndex, epIndex) \
usbInfo->devInfo.desc.interface[itfIndex].endpointDesc[epIndex].bInterval
/**@} end of group USBH_Core_Macros*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
USBH_STA_T USBH_GetDevDesc(USBH_INFO_T* usbInfo, uint8_t desLength);
USBH_STA_T USBH_SetAddr(USBH_INFO_T* usbInfo, uint8_t address);
USBH_STA_T USBH_GetCfgDesc(USBH_INFO_T* usbInfo, uint16_t desLength);
USBH_STA_T USBH_GetStringDesc(USBH_INFO_T* usbInfo, uint8_t stringIndex, \
uint8_t* buffer, uint16_t desLength);
USBH_STA_T USBH_REQ_GetDescriptor(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint16_t desType, uint8_t* buffer, uint16_t length);
USBH_STA_T USBH_SetConfiguration(USBH_INFO_T* usbInfo, uint16_t configuration);
USBH_STA_T USBH_SetFeature(USBH_INFO_T* usbInfo, uint8_t feature);
USBH_STA_T USBH_ClearFeature(USBH_INFO_T* usbInfo, uint8_t epNum);
USBH_STA_T USBH_REQ_CtrlXferHandler(USBH_INFO_T* usbInfo, uint8_t* buffer, uint16_t length);
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */
#endif

View file

@ -0,0 +1,123 @@
/*!
* @file usbh_core.c
*
* @brief USB host core function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_channel.h"
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
/*!
* @brief Clear all of the pipe data buffer.
*
* @param usbInfo
*
* @retval None
*/
void USBH_CH_Clear(USBH_INFO_T* usbInfo)
{
uint8_t i = 0;
for (i = 0; i < USBH_CHANNEL_MAX_NUM; i++)
{
usbInfo->xferChannel[i] = 0;
}
}
/*!
* @brief Get the free channel.
*
* @param usbInfo
*
* @retval None.
*/
uint16_t USBH_CH_ReadFreeChannel(USBH_INFO_T* usbInfo)
{
uint8_t i;
for (i = 0; i < USBH_CHANNEL_MAX_NUM; i++)
{
if ((usbInfo->xferChannel[i] & 0x8000) == 0)
{
return i;
}
}
return 0xFFFF;
}
/*!
* @brief Free the channel.
*
* @param usbInfo
*
* @param chNum : channel to be free.
*
* @retval None.
*/
void USBH_CH_FreeChannel(USBH_INFO_T* usbInfo, uint8_t chNum)
{
if (chNum < USBH_CHANNEL_MAX_NUM)
{
usbInfo->xferChannel[chNum] &= 0x7FFF;
}
}
/*!
* @brief Alloc a channel for a endpoint by address.
*
* @param usbInfo
*
* @param epAddr : endpoint address to be alloc channel.
*
* @retval channel number.
*/
uint8_t USBH_CH_AllocChannel(USBH_INFO_T* usbInfo, uint8_t epAddr)
{
uint16_t channelNum;
channelNum = USBH_CH_ReadFreeChannel(usbInfo);
if (channelNum != 0xFFFF)
{
usbInfo->xferChannel[channelNum & 0x0F] = (uint32_t)(0x8000 | epAddr);
}
return (uint8_t)channelNum;
}
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,808 @@
/*!
* @file usbh_dataXfer.c
*
* @brief USB host input and output hander function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_dataXfer.h"
#include "usbh_core.h"
#include "usbh_stdReq.h"
#include "usbh_channel.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
static USBH_STA_T USBH_CtrlXferIdle(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferSetup(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferSetupWait(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferInData(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferInDataWait(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferOutData(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferOutDataWait(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferInSta(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferInStaWait(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferOutSta(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferOutStaWait(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferError(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferStall(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_CtrlXferOk(USBH_INFO_T* usbInfo);
/**@} end of group USBH_Core_Functions */
/** @defgroup USBH_Core_Structures Structures
@{
*/
/* USB control transfer state handler function */
USBH_CtrlStateHandler_T USBH_CtrlStateHandler[] =
{
USBH_CtrlXferIdle,
USBH_CtrlXferSetup,
USBH_CtrlXferSetupWait,
USBH_CtrlXferInData,
USBH_CtrlXferInDataWait,
USBH_CtrlXferOutData,
USBH_CtrlXferOutDataWait,
USBH_CtrlXferInSta,
USBH_CtrlXferInStaWait,
USBH_CtrlXferOutSta,
USBH_CtrlXferOutStaWait,
USBH_CtrlXferError,
USBH_CtrlXferStall,
USBH_CtrlXferOk,
};
/**@} end of group USBH_Core_Structures*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
/*!
* @brief Control transfer send data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @param pingStatus : ping status
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length, \
uint8_t pingStatus)
{
USBH_STA_T usbStatus = USBH_OK;
if ((usbInfo->devInfo.speed != USBH_DEVICE_SPEED_HS) && (pingStatus == ENABLE))
{
pingStatus = DISABLE;
}
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_OUT, \
EP_TYPE_CONTROL, \
USBH_PID_DATA, \
(uint8_t*)buffer, \
length, \
pingStatus);
return usbStatus;
}
/*!
* @brief Control transfer receive data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_IN, \
EP_TYPE_CONTROL, \
USBH_PID_DATA, \
(uint8_t*)buffer, \
length, \
0);
return usbStatus;
}
/*!
* @brief Start control setup transfer
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be sent
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlSetupReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
USBH_REQ_DATA_T* buffer)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_OUT, \
EP_TYPE_CONTROL, \
USBH_PID_SETUP, \
(uint8_t*)buffer, \
USBH_SETUP_PACKET_SIZE, \
0);
return usbStatus;
}
/*!
* @brief Handle control idle state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferIdle(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
usbInfo->ctrl.state = USBH_CTRL_IDLE;
USBH_USR_Debug("USBH_CtrlXferIdle");
return usbStatus;
}
/*!
* @brief Handle control setup transfer
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferSetup(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferSetup");
/* Sent setup packet */
USBH_CtrlSetupReq(usbInfo, usbInfo->ctrl.channelOutNum, &usbInfo->ctrl.reqData);
usbInfo->ctrl.state = USBH_CTRL_SETUP_WAIT;
return usbStatus;
}
/*!
* @brief Handle control setup wait URB status transfer
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferSetupWait(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
uint16_t reqLenghTemp;
uint8_t reqDirTemp;
//static uint32_t timeout = 0;
USBH_USR_Debug("USBH_CtrlXferSetupWait");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbInfo->ctrl.channelOutNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
//timeout = 0;
reqDirTemp = usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir;
reqLenghTemp = usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] << 8 | \
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0];
/* Goto DATA state */
if (reqLenghTemp != 0)
{
if (reqDirTemp == USB_REQ_DIR_OUT)
{
usbInfo->ctrl.state = USBH_CTRL_DATA_OUT;
}
else
{
usbInfo->ctrl.state = USBH_CTRL_DATA_IN;
}
}
else
{
if (reqDirTemp == USB_REQ_DIR_OUT)
{
usbInfo->ctrl.state = USBH_CTRL_STA_IN;
}
else
{
usbInfo->ctrl.state = USBH_CTRL_STA_OUT;
}
}
break;
case USB_URB_ERROR:
case USB_URB_NOREADY:
//timeout = 0;
usbInfo->ctrl.state = USBH_CTRL_ERROR;
break;
default:
//timeout++;
break;
}
/*if(timeout >= 500)
{
timeout = 0;
usbInfo->ctrl.state = USBH_CTRL_ERROR;
}*/
return usbStatus;
}
/*!
* @brief Handle control IN state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferInData(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferInData");
USBH_CtrlReceiveDataReq(usbInfo, usbInfo->ctrl.channelInNum, \
usbInfo->ctrl.buffer, usbInfo->ctrl.length);
usbInfo->ctrl.state = USBH_CTRL_DATA_IN_WAIT;
return usbStatus;
}
/*!
* @brief Handle control IN wait URB status state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferInDataWait(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_USR_Debug("USBH_CtrlXferInDataWait");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbInfo->ctrl.channelInNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
usbInfo->ctrl.state = USBH_CTRL_STA_OUT;
break;
case USB_URB_STALL:
usbStatus = USBH_ERR_NOT_SUP;
break;
case USB_URB_ERROR:
usbInfo->ctrl.state = USBH_CTRL_ERROR;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief Handle control OUT state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferOutData(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferOutData");
USBH_CtrlSendDataReq(usbInfo, usbInfo->ctrl.channelOutNum, \
usbInfo->ctrl.buffer, usbInfo->ctrl.length, \
ENABLE);
usbInfo->ctrl.state = USBH_CTRL_DATA_OUT_WAIT;
return usbStatus;
}
/*!
* @brief Handle control OUT wait URB status state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferOutDataWait(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_USR_Debug("USBH_CtrlXferOutDataWait");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbInfo->ctrl.channelOutNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
usbInfo->ctrl.state = USBH_CTRL_STA_IN;
break;
case USB_URB_STALL:
usbInfo->ctrl.state = USBH_CTRL_STALL;
usbStatus = USBH_ERR_NOT_SUP;
break;
case USB_URB_NOREADY:
usbInfo->ctrl.state = USBH_CTRL_DATA_OUT;
break;
case USB_URB_ERROR:
usbInfo->ctrl.state = USBH_CTRL_ERROR;
usbStatus = USBH_FAIL;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief Handle control STATUS IN state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferInSta(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferInSta");
/* Send 0 byte out packet */
USBH_CtrlReceiveDataReq(usbInfo, usbInfo->ctrl.channelInNum, \
NULL, 0);
usbInfo->ctrl.state = USBH_CTRL_STA_IN_WAIT;
return usbStatus;
}
/*!
* @brief Handle control STATUS IN wait state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferInStaWait(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_USR_Debug("USBH_CtrlXferInStaWait");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbInfo->ctrl.channelInNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
usbInfo->ctrl.state = USBH_CTRL_OK;
usbStatus = USBH_OK;
break;
case USB_URB_STALL:
usbStatus = USBH_ERR_NOT_SUP;
break;
case USB_URB_ERROR:
usbInfo->ctrl.state = USBH_CTRL_ERROR;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief Handle control STATUS OUT state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferOutSta(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferOutSta");
/* Send 0 byte out packet */
USBH_CtrlSendDataReq(usbInfo, usbInfo->ctrl.channelOutNum, \
NULL, 0, ENABLE);
usbInfo->ctrl.state = USBH_CTRL_STA_OUT_WAIT;
return usbStatus;
}
/*!
* @brief Handle control STATUS OUT wait state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferOutStaWait(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
uint8_t usbUrbStatus = USB_URB_IDLE;
USBH_USR_Debug("USBH_CtrlXferOutStaWait");
/* Read USB URB status */
usbUrbStatus = USBH_ReadUrbStatusCallback(usbInfo, usbInfo->ctrl.channelOutNum);
switch (usbUrbStatus)
{
case USB_URB_OK:
usbInfo->ctrl.state = USBH_CTRL_OK;
usbStatus = USBH_OK;
break;
case USB_URB_NOREADY:
usbInfo->ctrl.state = USBH_CTRL_STA_OUT;
break;
case USB_URB_ERROR:
usbInfo->ctrl.state = USBH_CTRL_ERROR;
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief Handle control ERROR state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferError(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_CtrlXferError");
usbInfo->ctrl.errCnt++;
if (usbInfo->ctrl.errCnt > 2)
{
/* Notify user */
usbInfo->userCallback(usbInfo, USBH_USER_ERROR);
usbInfo->ctrl.errCnt = 0;
USBH_USR_LOG("Control error: Device No Response");
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelInNum);
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelOutNum);
usbInfo->hostState = USBH_HOST_IDLE;
usbStatus = USBH_FAIL;
// usbStatus = USBH_ERR_NOT_SUP;
}
else
{
/* Retry again */
usbInfo->ctrl.state = USBH_CTRL_SETUP;
usbInfo->xferState = USBH_XFER_START;
}
return usbStatus;
}
/*!
* @brief Handle control STALL state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferStall(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_ERR_NOT_SUP;
USBH_USR_Debug("USBH_CtrlXferStall");
return usbStatus;
}
/*!
* @brief Handle control OK state
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_CtrlXferOk(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbStatus = USBH_OK;
USBH_USR_Debug("USBH_CtrlXferOk");
return usbStatus;
}
/*!
* @brief Bulk transfer send data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @param pingStatus : ping status
*
* @retval usb host status
*/
USBH_STA_T USBH_BulkSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length, \
uint8_t pingStatus)
{
USBH_STA_T usbStatus = USBH_OK;
if ((usbInfo->devInfo.speed != USBH_DEVICE_SPEED_HS) && (pingStatus == ENABLE))
{
pingStatus = DISABLE;
}
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_OUT, \
EP_TYPE_BULK, \
USBH_PID_DATA, \
(uint8_t*)buffer, \
length, \
pingStatus);
return usbStatus;
}
/*!
* @brief Bulk transfer receive data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
USBH_STA_T USBH_BulkReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_IN, \
EP_TYPE_BULK, \
USBH_PID_DATA, \
buffer, \
length, \
0);
return usbStatus;
}
/*!
* @brief Interrupt transfer receive data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
USBH_STA_T USBH_IntReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_IN, \
EP_TYPE_INTERRUPT, \
USBH_PID_DATA, \
buffer, \
length, \
0);
return usbStatus;
}
/*!
* @brief Interrupt transfer send data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
USBH_STA_T USBH_IntSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_OUT, \
EP_TYPE_INTERRUPT, \
USBH_PID_DATA, \
buffer, \
length, \
0);
return usbStatus;
}
/*!
* @brief Isochronous transfer receive data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
USBH_STA_T USBH_IsoReceiveDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_IN, \
EP_TYPE_ISO, \
USBH_PID_DATA, \
buffer, \
length, \
0);
return usbStatus;
}
/*!
* @brief Isochronous transfer send data request
*
* @param usbInfo : usb handler information
*
* @param channelNum : channel number
*
* @param buffer : buffer to be receive data
*
* @param length : transfer length
*
* @retval usb host status
*/
USBH_STA_T USBH_IsoSendDataReq(USBH_INFO_T* usbInfo, uint8_t channelNum, \
uint8_t* buffer, uint8_t length)
{
USBH_STA_T usbStatus = USBH_OK;
/* Callback USB URB submit */
USBH_UrbSubmitCallback(usbInfo, channelNum, \
EP_DIR_OUT, \
EP_TYPE_ISO, \
USBH_PID_DATA, \
buffer, \
length, \
0);
return usbStatus;
}
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,495 @@
/*!
* @file usbh_enum.c
*
* @brief USB host enum hander function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_enum.h"
#include "usbh_stdReq.h"
#include "usbh_core.h"
#include <stdio.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
static USBH_STA_T USBH_ENUM_IdleHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetDevDescHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_SetAddressHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetConfigurationDescHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetFullConfigurationDescHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetMFCStringHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetProductStringHandler(USBH_INFO_T* usbInfo);
static USBH_STA_T USBH_ENUM_GetSerialNumStringHandler(USBH_INFO_T* usbInfo);
/**@} end of group USBH_Core_Functions */
/** @defgroup USBH_Core_Structures Structures
@{
*/
/* USB host enum state handler function */
USBH_EnumHandler_T USBH_EnumHandler[] =
{
USBH_ENUM_IdleHandler,
USBH_ENUM_GetDevDescHandler,
USBH_ENUM_SetAddressHandler,
USBH_ENUM_GetConfigurationDescHandler,
USBH_ENUM_GetFullConfigurationDescHandler,
USBH_ENUM_GetMFCStringHandler,
USBH_ENUM_GetProductStringHandler,
USBH_ENUM_GetSerialNumStringHandler,
};
/**@} end of group USBH_Core_Structures*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
/*!
* @brief Handle enum idle stage and get 8 bytes device descriptor
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_IdleHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
usbStatus = USBH_GetDevDesc(usbInfo, 0x08);
switch (usbStatus)
{
case USBH_OK:
usbInfo->ctrl.channelSize = usbInfo->devInfo.desc.device.bMaxPacketSize;
/* Open and config in channel */
USBH_OpenChannelCallback(usbInfo, usbInfo->ctrl.channelInNum,
0x80, usbInfo->devInfo.address,
usbInfo->devInfo.speed, EP_TYPE_CONTROL,
usbInfo->ctrl.channelSize);
/* Open and config out channel */
USBH_OpenChannelCallback(usbInfo, usbInfo->ctrl.channelOutNum,
0x00, usbInfo->devInfo.address,
usbInfo->devInfo.speed, EP_TYPE_CONTROL,
usbInfo->ctrl.channelSize);
usbInfo->hostEnumState = USBH_ENUM_GET_DEV_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("CTRL error: get device descriptor");
usbInfo->devInfo.enumCnt++;
if (usbInfo->devInfo.enumCnt <= 3)
{
/* Free control channel */
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelInNum);
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelOutNum);
/* Reset USB host state machine */
usbInfo->hostState = USBH_HOST_IDLE;
}
else
{
USBH_USR_LOG("CTRL error: device no response, please unplug the device");
usbInfo->hostState = USBH_HOST_ABORT;
}
break;
default:
break;
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get full bytes device descriptor stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetDevDescHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_GetDevDescHandler");
usbStatus = USBH_GetDevDesc(usbInfo, STD_DEV_DESC_SIZE);
switch (usbStatus)
{
case USBH_OK:
USBH_USR_LOG("PID: 0x%04X", usbInfo->devInfo.desc.device.idProduct[0] | \
usbInfo->devInfo.desc.device.idProduct[1] << 8);
USBH_USR_LOG("VID: 0x%04X", usbInfo->devInfo.desc.device.idVendor[0] | \
usbInfo->devInfo.desc.device.idVendor[1] << 8);
USBH_USR_LOG("Endpoint 0 max packet size if %d", usbInfo->devInfo.desc.device.bMaxPacketSize);
usbInfo->hostEnumState = USBH_ENUM_SET_ADDR;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("CTRL error: get full device descriptor");
usbInfo->devInfo.enumCnt++;
if (usbInfo->devInfo.enumCnt <= 3)
{
/* Free control channel */
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelInNum);
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelOutNum);
/* Reset USB host state machine */
usbInfo->hostState = USBH_HOST_IDLE;
usbInfo->hostEnumState = USBH_ENUM_IDLE;
}
else
{
USBH_USR_LOG("CTRL error: device no response, please unplug the device");
usbInfo->hostState = USBH_HOST_ABORT;
}
break;
default:
break;
}
return usbEnumStatus;
}
/*!
* @brief Handle enum set address stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_SetAddressHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_SetAddressHandler");
usbStatus = USBH_SetAddr(usbInfo, USBH_DEVICE_CONFIGURED_ADDRESS);
switch (usbStatus)
{
case USBH_OK:
/* Update device address */
usbInfo->devInfo.address = USBH_DEVICE_CONFIGURED_ADDRESS;
USBH_USR_LOG("USB device address: %d", usbInfo->devInfo.address);
USBH_Delay(5);
/* Modify channels to new device address */
/* Open and config out channel */
USBH_OpenChannelCallback(usbInfo, usbInfo->ctrl.channelOutNum,
0x00, usbInfo->devInfo.address,
usbInfo->devInfo.speed, EP_TYPE_CONTROL,
usbInfo->ctrl.channelSize);
/* Open and config in channel */
USBH_OpenChannelCallback(usbInfo, usbInfo->ctrl.channelInNum,
0x80, usbInfo->devInfo.address,
usbInfo->devInfo.speed, EP_TYPE_CONTROL,
usbInfo->ctrl.channelSize);
usbInfo->hostEnumState = USBH_ENUM_GET_CFG_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("CTRL error: set device address");
USBH_USR_LOG("CTRL error: device no response, please unplug the device");
usbInfo->hostState = USBH_HOST_ABORT;
usbInfo->hostEnumState = USBH_ENUM_IDLE;
break;
default:
break;
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get configuration descriptor stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetConfigurationDescHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_GetConfigurationDescHandler");
usbStatus = USBH_GetCfgDesc(usbInfo, STD_CFG_DESC_SIZE);
switch (usbStatus)
{
case USBH_OK:
usbInfo->hostEnumState = USBH_ENUM_GET_FULL_CFG_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("CTRL error: get configuration descriptor");
usbInfo->devInfo.enumCnt++;
if (usbInfo->devInfo.enumCnt <= 3)
{
/* Free control channel */
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelInNum);
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelOutNum);
/* Reset USB host state machine */
usbInfo->hostState = USBH_HOST_IDLE;
usbInfo->hostEnumState = USBH_ENUM_IDLE;
}
else
{
USBH_USR_LOG("CTRL error: device no response, please unplug the device");
usbInfo->hostState = USBH_HOST_ABORT;
}
break;
default:
break;
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get full configuration descriptor stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetFullConfigurationDescHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
uint16_t cfgDescTotalTemp;
USBH_USR_Debug("USBH_ENUM_GetFullConfigurationDescHandler");
cfgDescTotalTemp = usbInfo->devInfo.desc.configuration.wTotalLength[0] | \
usbInfo->devInfo.desc.configuration.wTotalLength[1] << 8;
usbStatus = USBH_GetCfgDesc(usbInfo, cfgDescTotalTemp);
switch (usbStatus)
{
case USBH_OK:
usbInfo->hostEnumState = USBH_ENUM_GET_MFC_STRING_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("CTRL error: get full configuration descriptor");
usbInfo->devInfo.enumCnt++;
if (usbInfo->devInfo.enumCnt <= 3)
{
/* Free control channel */
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelInNum);
USBH_CH_FreeChannel(usbInfo, usbInfo->ctrl.channelOutNum);
/* Reset USB host state machine */
usbInfo->hostState = USBH_HOST_IDLE;
usbInfo->hostEnumState = USBH_ENUM_IDLE;
}
else
{
USBH_USR_LOG("CTRL error: device no response, please unplug the device");
usbInfo->hostState = USBH_HOST_ABORT;
}
break;
default:
break;
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get manufacturer string stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetMFCStringHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_GetMFCStringHandler");
if (usbInfo->devInfo.desc.device.iManufacturer == 0)
{
USBH_USR_LOG("Manufacturer is N/A");
usbInfo->hostEnumState = USBH_ENUM_GET_PRODUCT_STRING_DESC;
}
else
{
usbStatus = USBH_GetStringDesc(usbInfo, usbInfo->devInfo.desc.device.iManufacturer, \
usbInfo->devInfo.desc.stringBuf, 0xFF);
switch (usbStatus)
{
case USBH_OK:
USBH_USR_LOG("Manufacturer: %s", (char*)usbInfo->devInfo.desc.stringBuf);
usbInfo->hostEnumState = USBH_ENUM_GET_PRODUCT_STRING_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("Manufacturer is N/A");
usbInfo->hostEnumState = USBH_ENUM_GET_PRODUCT_STRING_DESC;
break;
default:
break;
}
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get product string stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetProductStringHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_GetProductStringHandler");
if (usbInfo->devInfo.desc.device.iProduct == 0)
{
USBH_USR_LOG("Product is N/A");
usbInfo->hostEnumState = USBH_ENUM_GET_SERIALNUM_STRING_DESC;
}
else
{
usbStatus = USBH_GetStringDesc(usbInfo, usbInfo->devInfo.desc.device.iProduct, \
usbInfo->devInfo.desc.stringBuf, 0xFF);
switch (usbStatus)
{
case USBH_OK:
USBH_USR_LOG("Product: %s", (char*)usbInfo->devInfo.desc.stringBuf);
usbInfo->hostEnumState = USBH_ENUM_GET_SERIALNUM_STRING_DESC;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("Product is N/A");
usbInfo->hostEnumState = USBH_ENUM_GET_SERIALNUM_STRING_DESC;
break;
default:
break;
}
}
return usbEnumStatus;
}
/*!
* @brief Handle enum get serial number string stage
*
* @param usbInfo : usb handler information
*
* @retval usb host status
*/
static USBH_STA_T USBH_ENUM_GetSerialNumStringHandler(USBH_INFO_T* usbInfo)
{
USBH_STA_T usbEnumStatus = USBH_BUSY;
uint8_t usbStatus = USBH_BUSY;
USBH_USR_Debug("USBH_ENUM_GetSerialNumStringHandler");
if (usbInfo->devInfo.desc.device.iSerialNumber == 0)
{
USBH_USR_LOG("SerialNumber is N/A");
usbEnumStatus = USBH_OK;
}
else
{
usbStatus = USBH_GetStringDesc(usbInfo, usbInfo->devInfo.desc.device.iSerialNumber, \
usbInfo->devInfo.desc.stringBuf, 0xFF);
switch (usbStatus)
{
case USBH_OK:
USBH_USR_LOG("SerialNumber: %s", (char*)usbInfo->devInfo.desc.stringBuf);
usbEnumStatus = USBH_OK;
break;
case USBH_ERR_NOT_SUP:
USBH_USR_LOG("SerialNumber is N/A");
usbEnumStatus = USBH_OK;
break;
default:
break;
}
}
return usbEnumStatus;
}
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */

View file

@ -0,0 +1,723 @@
/*!
* @file usbh_stdReq.c
*
* @brief USB standard request process
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbh_stdReq.h"
#include "usbh_dataXfer.h"
#include "usbh_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBH_Core
@{
*/
/** @defgroup USBH_Core_Functions Functions
@{
*/
/*!
* @brief Parse string descriptor
*
* @param stringDesc : string descriptor
*
* @param buffer : source recevice data
*
* @param length : device descriptor length
*
* @retval usb host status
*/
USBH_STA_T USBH_StringDescParse(uint8_t* stringDesc, uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
uint8_t descType;
uint16_t stringLen;
uint16_t i;
descType = *(uint8_t*)(buffer + 1);
if (descType == USBH_DESC_STRING)
{
stringLen = *(uint8_t*)(buffer + 0) - 2;
if (stringLen > length)
{
stringLen = length;
}
buffer += 2;
/* only copy UNICODE bsting */
for (i = 0; i < stringLen; i += 2)
{
*stringDesc = buffer[i];
stringDesc++;
}
}
return usbStatus;
}
/*!
* @brief Copy data from source buffer to destination buffer.
*
* @param desBuffer: point to destination buffer
*
* @param srcBuf : point to source buffer
*
* @param len: copy length
*
* @retval None
*/
static void USBH_CopyBuffer(uint8_t* desBuffer, uint8_t* srcBuf, uint32_t len)
{
while (len--)
{
desBuffer[len] = srcBuf[len];
}
}
/*!
* @brief Parse configuration descriptor
*
* @param cfgDesc : configuration descriptor
*
* @param interface : interface of intDesc and epDesc
*
* @param buffer : source recevice data
*
* @param length : device descriptor length
*
* @retval usb host status
*/
USBH_STA_T USBH_CfgDescParse(USBH_CFG_DESC_T* cfgDesc, USBH_INTERFACE_T* interface, uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
uint16_t totalLenTemp = 0;
uint16_t parseIndex = 0;
uint8_t itfIndex = 0;
uint8_t epIndex = 0;
uint8_t subLen = 0;
cfgDesc->bLength = *(uint8_t*)(buffer + 0);
cfgDesc->bDescriptorType = *(uint8_t*)(buffer + 1);
totalLenTemp = *(uint8_t*)(buffer + 2) | (*(uint8_t*)(buffer + 3) << 8);
totalLenTemp = ((totalLenTemp) < (CFG_DESC_MAX_LEN) ? (totalLenTemp) : (CFG_DESC_MAX_LEN));
cfgDesc->wTotalLength[0] = totalLenTemp & 0xFF;
cfgDesc->wTotalLength[1] = (totalLenTemp >> 8) & 0xFF;
cfgDesc->bNumInterfaces = *(uint8_t*)(buffer + 4);
cfgDesc->bConfigurationValue = *(uint8_t*)(buffer + 5);
cfgDesc->iConfiguration = *(uint8_t*)(buffer + 6);
cfgDesc->bmAttributes = *(uint8_t*)(buffer + 7);
cfgDesc->bMaxPower = *(uint8_t*)(buffer + 8);
if (cfgDesc->bLength != STD_CFG_DESC_SIZE)
{
cfgDesc->bLength = STD_CFG_DESC_SIZE;
}
/* USB configuration descriptor lenght > STD_CFG_DESC_SIZE */
if (length > STD_CFG_DESC_SIZE)
{
parseIndex = STD_CFG_DESC_SIZE;
while (totalLenTemp > parseIndex)
{
/* Get descriptor length at first byte */
subLen = buffer[parseIndex];
/* Check the descriptor Type at second byte */
switch (buffer[parseIndex + 1])
{
case USBH_DESC_INTERFACE:
if (itfIndex < INTERFACE_DESC_MAX_NUM)
{
/* Move data from parse Buffer to Interface descriptor */
USBH_CopyBuffer((uint8_t*)&interface[itfIndex].interfaceDesc,
&buffer[parseIndex],
STD_INTERFACE_DESC_SIZE);
itfIndex++;
epIndex = 0;
}
break;
case USBH_DESC_ENDPOINT:
if ((itfIndex > 0) && (epIndex < ENDPOINT_DESC_MAX_NUM))
{
/* Move data from parse Buffer to Endpoint descriptor */
USBH_CopyBuffer((uint8_t*)&interface[itfIndex - 1].endpointDesc[epIndex],
&buffer[parseIndex],
STD_INTERFACE_DESC_SIZE);
epIndex++;
}
break;
default:
break;
}
parseIndex += subLen;
/* To avoid some useless data left */
if ((totalLenTemp - parseIndex) < STD_EP_DESC_SIZE)
{
break;
}
}
}
return usbStatus;
}
/*!
* @brief Parse device descriptor
*
* @param devDesc : device descriptor
*
* @param buffer : source recevice data
*
* @param length : device descriptor length
*
* @retval usb host status
*/
USBH_STA_T USBH_DevDescParse(USBH_DEV_DESC_T* devDesc, uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
devDesc->bLength = *(uint8_t*)(buffer + 0);
devDesc->bDescriptorType = *(uint8_t*)(buffer + 1);
devDesc->bcdUSB[0] = *(uint8_t*)(buffer + 2);
devDesc->bcdUSB[1] = *(uint8_t*)(buffer + 3);
devDesc->bDeviceClass = *(uint8_t*)(buffer + 4);
devDesc->bDeviceSubClass = *(uint8_t*)(buffer + 5);
devDesc->bDeviceProtocol = *(uint8_t*)(buffer + 6);
devDesc->bMaxPacketSize = *(uint8_t*)(buffer + 7);
switch (devDesc->bMaxPacketSize)
{
case 8:
case 16:
case 32:
case 64:
devDesc->bMaxPacketSize = devDesc->bMaxPacketSize;
break;
default:
devDesc->bMaxPacketSize = 64;
break;
}
if (length > 8)
{
devDesc->idVendor[0] = *(uint8_t*)(buffer + 8);
devDesc->idVendor[1] = *(uint8_t*)(buffer + 9);
devDesc->idProduct[0] = *(uint8_t*)(buffer + 10);
devDesc->idProduct[1] = *(uint8_t*)(buffer + 11);
devDesc->bcdDevice[0] = *(uint8_t*)(buffer + 12);
devDesc->bcdDevice[1] = *(uint8_t*)(buffer + 13);
devDesc->iManufacturer = *(uint8_t*)(buffer + 14);
devDesc->iProduct = *(uint8_t*)(buffer + 15);
devDesc->iSerialNumber = *(uint8_t*)(buffer + 16);
devDesc->bNumConfigurations = *(uint8_t*)(buffer + 17);
}
return usbStatus;
}
/*!
* @brief Handle control setup transfer.
*
* @param usbInfo : usb handler information
*
* @param buffer : control transfer buffer
*
* @param length : length of response
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_CtrlXferHandler(USBH_INFO_T* usbInfo, uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
USBH_USR_Debug("USBH_XFER_START");
usbInfo->ctrl.buffer = buffer;
usbInfo->ctrl.length = length;
usbInfo->ctrl.state = USBH_CTRL_SETUP;
usbInfo->xferState = USBH_XFER_WAITING;
usbStatus = USBH_BUSY;
break;
case USBH_XFER_WAITING:
USBH_USR_Debug("USBH_XFER_WAITING");
usbStatus = USBH_CtrlStateHandler[usbInfo->ctrl.state](usbInfo);
if ((usbStatus == USBH_OK) || (usbStatus == USBH_ERR_NOT_SUP))
{
usbInfo->xferState = USBH_XFER_START;
usbInfo->ctrl.state = USBH_CTRL_IDLE;
}
else if (usbStatus == USBH_FAIL)
{
usbInfo->xferState = USBH_XFER_START;
}
else
{
}
break;
}
return usbStatus;
}
/*!
* @brief USB host set device feature request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param feature : feature value
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_SetFeature(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t feature)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_STD_SET_FEATURE;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = feature;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief USB host clear device feature request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param feature : feature value
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_ClearFeature(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t epNum)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_STD_CLEAR_FEATURE;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = USBH_FEATURE_SELECTOR_ENDPOINT_HALT;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = epNum;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief USB host set device configuration request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param configuration : configuration value
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_SetConfiguration(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint16_t configuration)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_STD_SET_CONFIGURATION;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = configuration;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief USB host set device address request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type.
*
* @param addr : device address
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_SetAddr(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint8_t addr)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_STD_SET_ADDRESS;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = addr;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = 0;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, NULL, 0);
return usbStatus;
}
/*!
* @brief Config standard get descriptor request
*
* @param usbInfo : usb handler information
*
* @param reqType : Select request type
*
* @param desType : Specifies descriptor type
* This value can be one of the following values:
* @arg USBH_DESC_DEVICE
* @arg USBH_DESC_CONFIGURATION
* @arg USBH_DESC_STRING
* @arg USBH_DESC_INTERFACE
* @arg USBH_DESC_ENDPOINT
* @arg USBH_DESC_DEVICE_QUALIFIER
* @arg USBH_DESC_OTHER_SPEED
* @arg USBH_INTERFACE_POWER
*
* @param buffer : buffer to store descriptor
*
* @param length : Specifies len of request
*
* @retval usb host status
*/
USBH_STA_T USBH_REQ_GetDescriptor(USBH_INFO_T* usbInfo, uint8_t reqType, \
uint16_t desType, uint8_t* buffer, uint16_t length)
{
USBH_STA_T usbStatus = USBH_OK;
switch (usbInfo->xferState)
{
case USBH_XFER_START:
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.dir = ((reqType & 0x80) >> 7);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.type = ((reqType & 0x60) >> 5);
usbInfo->ctrl.reqData.DATA_FIELD.bmRequestType.REQ_TYPE_B.recipient = (reqType & 0x1F);
usbInfo->ctrl.reqData.DATA_FIELD.bRequest = USBH_STD_GET_DESCRIPTOR;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[0] = (desType >> 8) & 0xFF;
usbInfo->ctrl.reqData.DATA_FIELD.wValue[1] = desType & 0xFF;
if ((desType & 0xFF) == USBH_DESC_STRING)
{
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = USBH_LANG_ID & 0xFF;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = USBH_LANG_ID >> 8;
}
else
{
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[0] = 0;
usbInfo->ctrl.reqData.DATA_FIELD.wIndex[1] = 0;
}
usbInfo->ctrl.reqData.DATA_FIELD.wLength[0] = length & 0xFF;
usbInfo->ctrl.reqData.DATA_FIELD.wLength[1] = length >> 8;
break;
default:
break;
}
usbStatus = USBH_REQ_CtrlXferHandler(usbInfo, buffer, length);
return usbStatus;
}
/*!
* @brief USB host set feature
*
* @param usbInfo : usb handler information
*
* @param feature : value of feature
*
* @retval usb host status
*/
USBH_STA_T USBH_SetFeature(USBH_INFO_T* usbInfo, uint8_t feature)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_SetFeature(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)),
feature);
return usbStatus;
}
/*!
* @brief USB host clear feature
*
* @param usbInfo : usb handler information
*
* @param epNum : number of endpoint
*
* @retval usb host status
*/
USBH_STA_T USBH_ClearFeature(USBH_INFO_T* usbInfo, uint8_t epNum)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_ClearFeature(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_ENDPOINT)),
epNum);
return usbStatus;
}
/*!
* @brief USB host set configuration
*
* @param usbInfo : usb handler information
*
* @param configuration : value of configuration
*
* @retval usb host status
*/
USBH_STA_T USBH_SetConfiguration(USBH_INFO_T* usbInfo, uint16_t configuration)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_SetConfiguration(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)),
configuration);
return usbStatus;
}
/*!
* @brief USB host get configuration description
*
* @param usbInfo : usb handler information
*
* @param desLength : length of description
*
* @retval usb host status
*/
USBH_STA_T USBH_GetCfgDesc(USBH_INFO_T* usbInfo, uint16_t desLength)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_GetDescriptor(usbInfo, ((USBH_REQ_DIR_IN << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)), \
USBH_DESC_CONFIGURATION,
usbInfo->devInfo.desc.cfgDescBuf,
desLength);
if (usbStatus == USBH_OK)
{
/* Store received data */
USBH_CfgDescParse(&usbInfo->devInfo.desc.configuration, \
usbInfo->devInfo.desc.interface,
usbInfo->devInfo.desc.cfgDescBuf, desLength);
}
return usbStatus;
}
/*!
* @brief USB host get string description
*
* @param usbInfo : usb handler information
*
* @param stringIndex : string index
*
* @param buffer : buffer to store descriptor
*
* @param desLength : length of description
*
* @retval usb host status
*/
USBH_STA_T USBH_GetStringDesc(USBH_INFO_T* usbInfo, uint8_t stringIndex, uint8_t* buffer, uint16_t desLength)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_GetDescriptor(usbInfo, ((USBH_REQ_DIR_IN << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)), \
(USBH_DESC_STRING | stringIndex << 8),
usbInfo->devInfo.desc.stringBuf,
desLength);
if (usbStatus == USBH_OK)
{
/* Store received data */
USBH_StringDescParse(usbInfo->devInfo.desc.stringBuf, buffer, desLength);
}
return usbStatus;
}
/*!
* @brief USB host set device address
*
* @param usbInfo : usb handler information
*
* @param address : device address
*
* @retval usb host status
*/
USBH_STA_T USBH_SetAddr(USBH_INFO_T* usbInfo, uint8_t address)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_SetAddr(usbInfo, ((USBH_REQ_DIR_OUT << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)),
address);
return usbStatus;
}
/*!
* @brief USB host get device description
*
* @param usbInfo : usb handler information
*
* @param desLength : length of description
*
* @retval usb host status
*/
USBH_STA_T USBH_GetDevDesc(USBH_INFO_T* usbInfo, uint8_t desLength)
{
USBH_STA_T usbStatus = USBH_OK;
usbStatus = USBH_REQ_GetDescriptor(usbInfo, ((USBH_REQ_DIR_IN << 7) | \
(USBH_REQ_TYPE_STANDARD << 5) | \
(USBH_RECIPIENT_DEVICE)), \
USBH_DESC_DEVICE,
usbInfo->devInfo.data,
desLength);
if (usbStatus == USBH_OK)
{
/* Store received data */
USBH_DevDescParse(&usbInfo->devInfo.desc.device, usbInfo->devInfo.data, desLength);
}
return usbStatus;
}
/**@} end of group USBH_Core_Functions */
/**@} end of group USBH_Core */
/**@} end of group APM32_USB_Library */