aboutsummaryrefslogtreecommitdiff
path: root/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_usbhost.h
blob: 78b92b73313120be25a31e437ef2100b7f9fd75d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/********************************** (C) COPYRIGHT *******************************
 * File Name          : CH57x_usbhost.h
 * Author             : WCH
 * Version            : V1.2
 * Date               : 2021/11/17
 * Description
 *********************************************************************************
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for 
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/

#ifndef __CH58x_USBHOST_H__
#define __CH58x_USBHOST_H__

#ifdef __cplusplus
extern "C" {
#endif

#if DISK_LIB_ENABLE
  #if DISK_WITHOUT_USB_HUB
  /* 不使用U盘文件系统库或者U盘挂载USBhub下面,需要关闭下面定义 */
    #define FOR_ROOT_UDISK_ONLY
  #endif
  /* 使用U盘文件系统库,需要开启下面定义, 不使用请关闭 */
  #define DISK_BASE_BUF_LEN    512  /* 默认的磁盘数据缓冲区大小为512字节,建议选择为2048甚至4096以支持某些大扇区的U盘,为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 */
#endif

// 各子程序返回状态码
#define ERR_SUCCESS            0x00  // 操作成功
#define ERR_USB_CONNECT        0x15  /* 检测到USB设备连接事件,已经连接 */
#define ERR_USB_DISCON         0x16  /* 检测到USB设备断开事件,已经断开 */
#define ERR_USB_BUF_OVER       0x17  /* USB传输的数据有误或者数据太多缓冲区溢出 */
#define ERR_USB_DISK_ERR       0x1F  /* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */
#define ERR_USB_TRANSFER       0x20  /* NAK/STALL等更多错误码在0x20~0x2F */
#define ERR_USB_UNSUPPORT      0xFB  /* 不支持的USB设备*/
#define ERR_USB_UNKNOWN        0xFE  /* 设备操作出错*/
#define ERR_AOA_PROTOCOL       0x41  /* 协议版本出错 */

/*USB设备相关信息表,最多支持1个设备*/
#define ROOT_DEV_DISCONNECT    0
#define ROOT_DEV_CONNECTED     1
#define ROOT_DEV_FAILED        2
#define ROOT_DEV_SUCCESS       3
#define DEV_TYPE_KEYBOARD      (USB_DEV_CLASS_HID | 0x20)
#define DEV_TYPE_MOUSE         (USB_DEV_CLASS_HID | 0x30)
#define DEF_AOA_DEVICE         0xF0
#define DEV_TYPE_UNKNOW        0xFF

/*
约定: USB设备地址分配规则(参考USB_DEVICE_ADDR)
地址值  设备位置
0x02    内置Root-HUB下的USB设备或外部HUB
0x1x    内置Root-HUB下的外部HUB的端口x下的USB设备,x为1~n
*/
#define HUB_MAX_PORTS          4
#define WAIT_USB_TOUT_200US    800   // 等待USB中断超时时间

typedef struct
{
    uint8_t  DeviceStatus;  // 设备状态,0-无设备,1-有设备但尚未初始化,2-有设备但初始化枚举失败,3-有设备且初始化枚举成功
    uint8_t  DeviceAddress; // 设备被分配的USB地址
    uint8_t  DeviceSpeed;   // 0为低速,非0为全速
    uint8_t  DeviceType;    // 设备类型
    uint16_t DeviceVID;
    uint16_t DevicePID;
    uint8_t  GpVar[4];     // 通用变量,存放端点
    uint8_t  GpHUBPortNum; // 通用变量,如果是HUB,表示HUB端口数
} _RootHubDev;

typedef struct
{
    UINT8  DeviceStatus;  // 设备状态,0-无设备,1-有设备但尚未初始化,2-有设备但初始化枚举失败,3-有设备且初始化枚举成功
    UINT8  DeviceAddress; // 设备被分配的USB地址
    UINT8  DeviceSpeed;   // 0为低速,非0为全速
    UINT8  DeviceType;    // 设备类型
    UINT16 DeviceVID;
    UINT16 DevicePID;
    UINT8  GpVar[4]; // 通用变量
} _DevOnHubPort;     // 假定:不超过1个外部HUB,每个外部HUB不超过HUB_MAX_PORTS个端口(多了不管)

extern _RootHubDev   ThisUsbDev;
extern _DevOnHubPort DevOnHubPort[HUB_MAX_PORTS]; // 假定:不超过1个外部HUB,每个外部HUB不超过HUB_MAX_PORTS个端口(多了不管)
extern uint8_t       UsbDevEndp0Size;             // USB设备的端点0的最大包尺寸 */
extern uint8_t       FoundNewDev;

extern uint8_t *pHOST_RX_RAM_Addr;
extern uint8_t *pHOST_TX_RAM_Addr;

extern _RootHubDev   ThisUsb2Dev;
extern _DevOnHubPort DevOnU2HubPort[HUB_MAX_PORTS]; // 假定:不超过1个外部HUB,每个外部HUB不超过HUB_MAX_PORTS个端口(多了不管)
extern uint8_t       Usb2DevEndp0Size;              // USB设备的端点0的最大包尺寸 */
extern uint8_t       FoundNewU2Dev;

extern uint8_t *pU2HOST_RX_RAM_Addr;
extern uint8_t *pU2HOST_TX_RAM_Addr;

#define pSetupReq      ((PUSB_SETUP_REQ)pHOST_TX_RAM_Addr)
#define pU2SetupReq    ((PUSB_SETUP_REQ)pU2HOST_TX_RAM_Addr)
extern uint8_t Com_Buffer[];
extern uint8_t U2Com_Buffer[];

/* 以下为USB主机请求包 */
extern const uint8_t SetupGetDevDescr[];     // 获取设备描述符*/
extern const uint8_t SetupGetCfgDescr[];     // 获取配置描述符*/
extern const uint8_t SetupSetUsbAddr[];      // 设置USB地址*/
extern const uint8_t SetupSetUsbConfig[];    // 设置USB配置*/
extern const uint8_t SetupSetUsbInterface[]; // 设置USB接口配置*/
extern const uint8_t SetupClrEndpStall[];    // 清除端点STALL*/

extern const uint8_t SetupGetU2DevDescr[];    // 获取设备描述符*/
extern const uint8_t SetupGetU2CfgDescr[];    // 获取配置描述符*/
extern const uint8_t SetupSetUsb2Addr[];      // 设置USB地址*/
extern const uint8_t SetupSetUsb2Config[];    // 设置USB配置*/
extern const uint8_t SetupSetUsb2Interface[]; // 设置USB接口配置*/
extern const uint8_t SetupClrU2EndpStall[];   // 清除端点STALL*/

/**
 * @brief   关闭ROOT-HUB端口,实际上硬件已经自动关闭,此处只是清除一些结构状态
 */
void DisableRootHubPort(void);

/**
 * @brief   分析ROOT-HUB状态,处理ROOT-HUB端口的设备插拔事件
 *          如果设备拔出,函数中调用DisableRootHubPort()函数,将端口关闭,插入事件,置相应端口的状态位
 *
 * @return  返回ERR_SUCCESS为没有情况,返回ERR_USB_CONNECT为检测到新连接,返回ERR_USB_DISCON为检测到断开
 */
uint8_t AnalyzeRootHub(void);

/**
 * @brief   设置USB主机当前操作的USB设备地址
 *
 * @param   addr    - USB设备地址
 */
void SetHostUsbAddr(uint8_t addr);

/**
 * @brief   设置当前USB速度
 *
 * @param   FullSpeed   - USB速度
 */
void SetUsbSpeed(uint8_t FullSpeed);

/**
 * @brief   检测到设备后,复位总线,为枚举设备准备,设置为默认为全速
 */
void ResetRootHubPort(void);

/**
 * @brief   使能ROOT-HUB端口,相应的bUH_PORT_EN置1开启端口,设备断开可能导致返回失败
 *
 * @return  返回ERR_SUCCESS为检测到新连接,返回ERR_USB_DISCON为无连接
 */
uint8_t EnableRootHubPort(void);

/**
 * @brief   等待USB中断
 *
 * @return  返回ERR_SUCCESS 数据接收或者发送成功,返回ERR_USB_UNKNOWN 数据接收或者发送失败
 */
uint8_t WaitUSB_Interrupt(void);

/**
 * @brief   传输事务,输入目的端点地址/PID令牌,同步标志,以20uS为单位的NAK重试总时间(0则不重试,0xFFFF无限重试),返回0成功,超时/出错重试
 *          本子程序着重于易理解,而在实际应用中,为了提供运行速度,应该对本子程序代码进行优化
 *
 * @param   endp_pid    - 令牌和地址, 高4位是token_pid令牌, 低4位是端点地址
 * @param   tog         - 同步标志
 * @param   timeout     - 超时时间
 *
 * @return  ERR_USB_UNKNOWN 超时,可能硬件异常
 *          ERR_USB_DISCON  设备断开
 *          ERR_USB_CONNECT 设备连接
 *          ERR_SUCCESS     传输完成
 */
uint8_t USBHostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout);

/**
 * @brief   执行控制传输,8字节请求码在pSetupReq中,DataBuf为可选的收发缓冲区
 *
 * @param   DataBuf     - 如果需要接收和发送数据,那么DataBuf需指向有效缓冲区用于存放后续数据
 * @param   RetLen      - 实际成功收发的总长度保存在RetLen指向的字节变量中
 *
 * @return  ERR_USB_BUF_OVER    IN状态阶段出错
 *          ERR_SUCCESS         数据交换成功
 */
uint8_t HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen);

/**
 * @brief   复制控制传输的请求包
 *
 * @param   pReqPkt     - 控制请求包地址
 */
void CopySetupReqPkg(const uint8_t *pReqPkt);

/**
 * @brief   获取设备描述符,返回在 pHOST_TX_RAM_Addr 中
 *
 * @return  ERR_USB_BUF_OVER    描述符长度错误
 *          ERR_SUCCESS         成功
 */
uint8_t CtrlGetDeviceDescr(void);

/**
 * @brief   获取配置描述符,返回在 pHOST_TX_RAM_Addr 中
 *
 * @return  ERR_USB_BUF_OVER    描述符长度错误
 *          ERR_SUCCESS         成功
 */
uint8_t CtrlGetConfigDescr(void);

/**
 * @brief   设置USB设备地址
 *
 * @param   addr    - 设备地址
 *
 * @return  ERR_SUCCESS     成功
 */
uint8_t CtrlSetUsbAddress(uint8_t addr);

/**
 * @brief   设置USB设备配置
 *
 * @param   cfg     - 配置值
 *
 * @return  ERR_SUCCESS     成功
 */
uint8_t CtrlSetUsbConfig(uint8_t cfg);

/**
 * @brief   清除端点STALL
 *
 * @param   endp    - 端点地址
 *
 * @return  ERR_SUCCESS     成功
 */
uint8_t CtrlClearEndpStall(uint8_t endp);

/**
 * @brief   设置USB设备接口
 *
 * @param   cfg     - 配置值
 *
 * @return  ERR_SUCCESS     成功
 */
uint8_t CtrlSetUsbIntercace(uint8_t cfg);

/**
 * @brief   USB主机功能初始化
 */
void USB_HostInit(void);
uint8_t EnumAllHubPort(void);// 枚举所有ROOT-HUB端口下外部HUB后的二级USB设备
void SelectHubPort(uint8_t HubPortIndex); // HubPortIndex=0选择操作指定的ROOT-HUB端口,否则选择操作指定的ROOT-HUB端口的外部HUB的指定端口
uint16_t SearchTypeDevice(uint8_t type); // 在ROOT-HUB以及外部HUB各端口上搜索指定类型的设备所在的端口号,输出端口号为0xFFFF则未搜索到.
uint8_t SETorOFFNumLock(uint8_t *buf); // NumLock的点灯判断

void    DisableRootU2HubPort(void); // 关闭ROOT-U2HUB端口,实际上硬件已经自动关闭,此处只是清除一些结构状态
uint8_t AnalyzeRootU2Hub(void);     // 分析ROOT-U2HUB状态,处理ROOT-U2HUB端口的设备插拔事件
// 返回ERR_SUCCESS为没有情况,返回ERR_USB_CONNECT为检测到新连接,返回ERR_USB_DISCON为检测到断开
void    SetHostUsb2Addr(uint8_t addr);         // 设置USB主机当前操作的USB设备地址
void    SetUsb2Speed(uint8_t FullSpeed);       // 设置当前USB速度
void    ResetRootU2HubPort(void);              // 检测到设备后,复位相应端口的总线,为枚举设备准备,设置为默认为全速
uint8_t EnableRootU2HubPort(void);             // 使能ROOT-HUB端口,相应的bUH_PORT_EN置1开启端口,设备断开可能导致返回失败
void    SelectU2HubPort(uint8_t HubPortIndex); // HubPortIndex=0选择操作指定的ROOT-HUB端口,否则选择操作指定的ROOT-HUB端口的外部HUB的指定端口
uint8_t WaitUSB2_Interrupt(void);              // 等待USB中断
// 传输事务,输入目的端点地址/PID令牌,同步标志,以20uS为单位的NAK重试总时间(0则不重试,0xFFFF无限重试),返回0成功,超时/出错重试
uint8_t USB2HostTransact(uint8_t endp_pid, uint8_t tog, UINT32 timeout); // endp_pid: 高4位是token_pid令牌, 低4位是端点地址
uint8_t U2HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen);           // 执行控制传输,8字节请求码在pSetupReq中,DataBuf为可选的收发缓冲区
// 如果需要接收和发送数据,那么DataBuf需指向有效缓冲区用于存放后续数据,实际成功收发的总长度返回保存在ReqLen指向的字节变量中

void    CopyU2SetupReqPkg(const uint8_t *pReqPkt); // 复制控制传输的请求包
uint8_t CtrlGetU2DeviceDescr(void);                // 获取设备描述符,返回在 pHOST_TX_RAM_Addr 中
uint8_t CtrlGetU2ConfigDescr(void);                // 获取配置描述符,返回在 pHOST_TX_RAM_Addr 中
uint8_t CtrlSetUsb2Address(uint8_t addr);          // 设置USB设备地址
uint8_t CtrlSetUsb2Config(uint8_t cfg);            // 设置USB设备配置
uint8_t CtrlClearU2EndpStall(uint8_t endp);        // 清除端点STALL
uint8_t CtrlSetUsb2Intercace(uint8_t cfg);         // 设置USB设备接口

void USB2_HostInit(void); // 初始化USB主机

/*************************************************************/

/**
 * @brief   初始化指定ROOT-HUB端口的USB设备
 *
 * @return  错误码
 */
uint8_t InitRootDevice(void);

/**
 * @brief   获取HID设备报表描述符,返回在TxBuffer中
 *
 * @return  错误码
 */
uint8_t CtrlGetHIDDeviceReport(uint8_t infc);

/**
 * @brief   获取HUB描述符,返回在Com_Buffer中
 *
 * @return  错误码
 */
uint8_t CtrlGetHubDescr(void);

/**
 * @brief   查询HUB端口状态,返回在Com_Buffer中
 *
 * @param   HubPortIndex    - 端口号
 *
 * @return  错误码
 */
uint8_t HubGetPortStatus(uint8_t HubPortIndex);

/**
 * @brief   设置HUB端口特性
 *
 * @param   HubPortIndex    - 端口号
 * @param   FeatureSelt     - 端口特性
 *
 * @return  错误码
 */
uint8_t HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt);

/**
 * @brief   清除HUB端口特性
 *
 * @param   HubPortIndex    - 端口号
 * @param   FeatureSelt     - 端口特性
 *
 * @return  错误码
 */
uint8_t HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt);

uint8_t  InitRootU2Device(void);
uint8_t  EnumAllU2HubPort(void);
uint16_t U2SearchTypeDevice(uint8_t type);
uint8_t  U2SETorOFFNumLock(uint8_t *buf);

uint8_t CtrlGetU2HIDDeviceReport(uint8_t infc);                           // HID类命令,SET_IDLE和GET_REPORT
uint8_t CtrlGetU2HubDescr(void);                                          // 获取HUB描述符,返回在TxBuffer中
uint8_t U2HubGetPortStatus(uint8_t HubPortIndex);                         // 查询HUB端口状态,返回在TxBuffer中
uint8_t U2HubSetPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt);   // 设置HUB端口特性
uint8_t U2HubClearPortFeature(uint8_t HubPortIndex, uint8_t FeatureSelt); // 清除HUB端口特性

#ifdef __cplusplus
}
#endif

#endif // __CH58x_USBHOST_H__