/********************************** (C) COPYRIGHT ******************************* * File Name : CH59x_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 __CH59x_USBHOST_H__ #define __CH59x_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的点灯判断 /*************************************************************/ /** * @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); #ifdef __cplusplus } #endif #endif // __CH59x_USBHOST_H__