From 0412b6b68573c881b64f83eb7c9d8576aeb6e379 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sat, 17 Sep 2022 14:00:04 +0800 Subject: [PATCH] update doc --- README.md | 13 +-- README_zh.md | 13 +-- docs/source/api/api_device.rst | 2 +- docs/source/api/api_host.rst | 108 +++++++++++------------ docs/source/api/api_port.rst | 152 +++++++++++---------------------- docs/source/index.rst | 13 +-- 6 files changed, 124 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 29063a88..a879bce3 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ CherryUSB is a tiny, beautiful and portable USB host and device stack for embedd ## Why choose -- More comprehensive class drivers, and class drivers are all templated, easy to learn and add independently -- Tree programming, easy to understand the relationship between class driver and interface, endpoint, the relationship between hub, port, class; code layer by layer, call relationship at a glance, easy to understand the usb enumeration process and class driver loading -- The use of device protocol stacks is equivalent to uart tx/rx dma, and the use of the host stack is equivalent to file opertion. -- Standardized porting interface, as well as ip-oriented programming, eliminating the need to rewrite drivers for the same ip -- Api less, clear classification: dcd/hcd api, registration api, command callback api -- Streamlined code, minimal memory footprint, and the ip driver code is also streamlined to achieve the theoretical bandwidth of the usb hardware +- Streamlined code with small memory usage which also can be further trimmed +- Comprehensive class drivers and all master and slave class drivers are templated,making it easy for users to add new class drivers and find patterns when learning +- The APIs available to the users are very few and clearly categorised. Device: initialisation + registration apis, command callback apis, data sending and receiving apis; Host: initialisation + lookup apis, data sending and receiving apis +- Tree-based programming with a hierarchy of code that makes it easy for the user to sort out function call relationships, enumerations and class-driven loading processes +- Standardised porting interface, no need to rewrite the driver for the same ip, and porting drivers are templated to make it easier for users to add new ports +- The use of the device or host transceiver apis are equivalent to the use of the uart tx/rx dma, and there is no limit to the length +- Capable of achieving theoretical USB hardware bandwidth ## Directoy Structure diff --git a/README_zh.md b/README_zh.md index b052683e..5b239c14 100644 --- a/README_zh.md +++ b/README_zh.md @@ -8,12 +8,13 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 ## 为什么选择 -- 比较全面的 class 驱动,并且 class 驱动全部模板化,方便学习和自主添加 -- 树状化编程,方便理清 class 驱动与接口、端点的关系,hub、port、class 之间的关系;代码层层递进,调用关系一目了然,方便理清 usb 枚举过程和 class 驱动加载 -- 设备协议栈使用等价于 uart tx/rx dma 的使用,主机协议栈的使用等价于文件的使用 -- 标准化的 porting 接口,同时面向 ip 化编程,相同 ip 无需重复编写驱动 -- Api 少,分类清晰:dcd/hcd api、注册 api、命令回调 api -- 协议栈代码精简,内存占用极小,ip 驱动代码也做到精简,能够达到 usb 硬件理论带宽 +- 代码精简,并且内存占用极小,详细参考下面表格,而且还可进一步的裁剪 +- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律 +- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册类、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类 +- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程 +- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。 +- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制 +- 能够达到 USB 硬件理论带宽 ## 目录结构 diff --git a/docs/source/api/api_device.rst b/docs/source/api/api_device.rst index 7b8f545b..6b32c446 100644 --- a/docs/source/api/api_device.rst +++ b/docs/source/api/api_device.rst @@ -4,7 +4,7 @@ 设备协议栈主要负责枚举和驱动加载,枚举这边就不说了,驱动加载,也就是接口驱动加载,主要是依靠 `usbd_add_interface` 函数,记录传入的接口驱动保存到链表中,当主机进行类请求时就可以查找链表进行访问了。 在调用 `usbd_desc_register` 以后需要进行接口注册和端点注册,口诀如下: -- 有多少个接口就调用多少次 `usbd_add_interface`,参数填各个 class alloc 出来的 intf,如果没有 alloc 的intf 表示不需要加载。 +- 有多少个接口就调用多少次 `usbd_add_interface`,参数填相关 `xxx_alloc_intf`, 如果没有支持的,手动创建一个填入 - 有多少个端点就调用多少次 `usbd_add_endpoint`,当中断完成时,会调用到注册的端点回调中。 CORE diff --git a/docs/source/api/api_host.rst b/docs/source/api/api_host.rst index 92c42d00..979aaa8e 100644 --- a/docs/source/api/api_host.rst +++ b/docs/source/api/api_host.rst @@ -15,11 +15,12 @@ CLASS 驱动信息结构体 .. code-block:: C struct usbh_class_info { - uint8_t class; /* Base device class code */ - uint8_t subclass; /* Sub-class, depends on base class. Eg. */ - uint8_t protocol; /* Protocol, depends on base class. Eg. */ - uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ - uint16_t pid; /* Product ID (for vendor/product specific devices) */ + uint8_t match_flags; /* Used for product specific matches; range is inclusive */ + uint8_t class; /* Base device class code */ + uint8_t subclass; /* Sub-class, depends on base class. Eg. */ + uint8_t protocol; /* Protocol, depends on base class. Eg. */ + uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ + uint16_t pid; /* Product ID (for vendor/product specific devices) */ const struct usbh_class_driver *class_driver; }; @@ -28,99 +29,90 @@ CLASS 驱动信息结构体 .. code-block:: C - typedef struct usbh_endpoint { + struct usbh_endpoint { struct usb_endpoint_descriptor ep_desc; - } usbh_endpoint_t; + }; + +接口备用结构体 +"""""""""""""""""""""""""""""""""""" + +.. code-block:: C + + struct usbh_interface_altsetting { + struct usb_interface_descriptor intf_desc; + struct usbh_endpoint ep[CONFIG_USBHOST_MAX_ENDPOINTS]; + }; 接口结构体 """""""""""""""""""""""""""""""""""" .. code-block:: C - typedef struct usbh_interface { - struct usb_interface_descriptor intf_desc; - struct usbh_endpoint ep[CONFIG_USBHOST_EP_NUM]; + struct usbh_interface { + struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS]; + uint8_t altsetting_num; char devname[CONFIG_USBHOST_DEV_NAMELEN]; struct usbh_class_driver *class_driver; void *priv; - } usbh_interface_t; - + }; 配置结构体 """""""""""""""""""""""""""""""""""" .. code-block:: C - typedef struct usbh_configuration { + struct usbh_configuration { struct usb_configuration_descriptor config_desc; - struct usbh_interface intf[CONFIG_USBHOST_INTF_NUM]; - } usbh_configuration_t; + struct usbh_interface intf[CONFIG_USBHOST_MAX_INTERFACES]; + }; hubport 结构体 """""""""""""""""""""""""""""""""""" .. code-block:: C - typedef struct usbh_hubport { - bool connected; /* True: device connected; false: disconnected */ - bool port_change; /* True: port changed; false: port do not change */ - uint8_t port; /* Hub port index */ - uint8_t dev_addr; /* device address */ - uint8_t speed; /* device speed */ - usbh_epinfo_t ep0; /* control ep info */ + struct usbh_hubport { + bool connected; /* True: device connected; false: disconnected */ + uint8_t port; /* Hub port index */ + uint8_t dev_addr; /* device address */ + uint8_t speed; /* device speed */ + usbh_pipe_t ep0; /* control ep pipe info */ struct usb_device_descriptor device_desc; struct usbh_configuration config; + const char *iManufacturer; + const char *iProduct; + const char *iSerialNumber; #if 0 - uint8_t* config_desc; + uint8_t* raw_config_desc; #endif - struct usb_setup_packet *setup; - struct usbh_hub *parent; /*if NULL, is roothub*/ - } usbh_hubport_t; + USB_MEM_ALIGNX struct usb_setup_packet setup; + struct usbh_hub *parent; + }; hub 结构体 """""""""""""""""""""""""""""""""""" .. code-block:: C - typedef struct usbh_hub { + struct usbh_hub { usb_slist_t list; - uint8_t index; /* Hub index */ - uint8_t nports; /* Hub port number */ - uint8_t dev_addr; /* Hub device address */ - usbh_epinfo_t intin; - uint8_t *int_buffer; - struct hub_port_status *port_status; + bool connected; + bool is_roothub; + uint8_t index; + uint8_t hub_addr; + usbh_pipe_t intin; + USB_MEM_ALIGNX uint8_t int_buffer[1]; + struct usbh_urb intin_urb; struct usb_hub_descriptor hub_desc; - struct usbh_hubport child[CONFIG_USBHOST_EHPORTS]; - struct usbh_hubport *parent; /* Parent hub port */ - struct usb_work work; - } usbh_hub_t; - -usbh_event_notify_handler -"""""""""""""""""""""""""""""""""""" - -``usbh_event_notify_handler`` 是 USB 中断中的核心,主要用于处理 **设备连接** 和 **设备断开** 中断,从而唤醒线程去执行枚举。 - -.. code-block:: C - - void usbh_event_notify_handler(uint8_t event, uint8_t rhport); - -- **event** 中断事件 -- **rhport** roothub 端口号 - -其中 ``event`` 有如下类型: - -.. code-block:: C - - enum usbh_event_type { - USBH_EVENT_ATTACHED, - USBH_EVENT_REMOVED, + struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS]; + struct usbh_hubport *parent; + usb_slist_t hub_event_list; }; usbh_initialize """""""""""""""""""""""""""""""""""" -``usbh_initialize`` 用来初始化 usb 主机协议栈,包括:创建插拔检测用的信号量和枚举线程、高低工作队列、初始化 roothub 端点0 配置,初始化 usb 主机控制器。 +``usbh_initialize`` 用来初始化 usb 主机协议栈,包括:初始化 usb 主机控制器,创建 roothub 设备,创建 hub 检测线程。 .. code-block:: C diff --git a/docs/source/api/api_port.rst b/docs/source/api/api_port.rst index 649bc22a..1fe9716b 100644 --- a/docs/source/api/api_port.rst +++ b/docs/source/api/api_port.rst @@ -140,112 +140,100 @@ usb_hc_init - **return** 返回 0 表示正确,其他表示错误 -usbh_get_port_connect_status +usbh_roothub_control """""""""""""""""""""""""""""""""""" -``usbh_get_port_connect_status`` 获取当前 hubport 连接状态。 **此函数不对用户开放**。 +``usbh_roothub_control`` 用来对 roothub 发起请求, **此函数不对用户开放**。 .. code-block:: C - int usbh_get_port_connect_status(const uint8_t port); + int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf); -- **port** 端口号 -- **return** 返回 1 表示连接,0 表示未连接 - -usbh_reset_port -"""""""""""""""""""""""""""""""""""" - -``usbh_reset_port`` 复位指定的 hubport **此函数不对用户开放**。 - -.. code-block:: C - - int usbh_reset_port(const uint8_t port); - -- **port** 端口号 +- **setup** 请求 +- **buf** 接收缓冲区 - **return** 返回 0 表示正确,其他表示错误 -usbh_get_port_speed +usbh_ep0_pipe_reconfigure """""""""""""""""""""""""""""""""""" -``usbh_get_port_speed`` 获取当前 hubport 上连接的设备速度。 **此函数不对用户开放**。 +``usbh_ep0_pipe_reconfigure`` 重新设置端点 0 的 pipe 属性。 **此函数不对用户开放**。 .. code-block:: C - int usbh_get_port_speed(const uint8_t port); + int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed); -- **port** 端口号 -- **return** 返回 1 表示低速,2 表示全速,3 表示高速 - -usbh_ep0_reconfigure -"""""""""""""""""""""""""""""""""""" - -``usbh_ep0_reconfigure`` 重新设置端点 0 的属性。 **此函数不对用户开放**。 - -.. code-block:: C - - int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed); - -- **ep** 端点信息 +- **pipe** pipe 句柄 - **dev_addr** 端点所在设备地址 - **ep_mps** 端点最大包长 - **speed** 端点所在设备的速度 - **return** 返回 0 表示正确,其他表示错误 -usbh_ep_alloc +usbh_pipe_alloc """""""""""""""""""""""""""""""""""" -``usbh_ep_alloc`` 为端点分配相关属性,初始化相关寄存器,并保存相关信息到 **ep** 句柄中。 **此函数不对用户开放**。 +``usbh_pipe_alloc`` 为端点分配 pipe。 **此函数不对用户开放**。 .. code-block:: C - int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg); + int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg); -- **ep** 端点信息 +- **pipe** pipe 句柄 - **ep_cfg** 端点初始化需要的一些信息 - **return** 返回 0 表示正确,其他表示错误 -usbh_ep_free +usbh_pipe_free """""""""""""""""""""""""""""""""""" -``usbh_ep_free`` 释放端点的一些属性。 **此函数不对用户开放**。 +``usbh_pipe_free`` 释放端点的一些属性。 **此函数不对用户开放**。 .. code-block:: C - int usbh_ep_free(usbh_epinfo_t ep); + int usbh_pipe_free(usbh_pipe_t pipe); -- **ep** 端点信息 +- **pipe** 端点信息 - **return** 返回 0 表示正确,其他表示错误 -usbh_control_transfer +usbh_submit_urb """""""""""""""""""""""""""""""""""" -``usbh_control_transfer`` 对端点 0 进行控制传输,并且 **此函数为阻塞式传输,默认超时时间 5s**。 **此函数对用户开放**。 +``usbh_submit_urb`` 对某个地址上的端点进行数据请求。 **此函数对用户开放**。 .. code-block:: C - int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer); + int usbh_submit_urb(struct usbh_urb *urb); -- **ep** 端点信息 -- **setup** setup 包 -- **buffer** 要发送或者读取的数据缓冲区,为 NULL 表示没有数据要发送或者接收 +- **urb** usb 请求块 - **return** 返回 0 表示正确,其他表示错误 -usbh_ep_bulk_transfer -"""""""""""""""""""""""""""""""""""" - -``usbh_ep_bulk_transfer`` 对指定端点进行批量传输, **此函数为阻塞式传输**。 **此函数对用户开放**。 +其中, `urb` 结构体信息如下: .. code-block:: C - int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout); + struct usbh_urb { + usbh_pipe_t pipe; + struct usb_setup_packet *setup; + uint8_t *transfer_buffer; + uint32_t transfer_buffer_length; + int transfer_flags; + uint32_t actual_length; + uint32_t timeout; + int errorcode; + usbh_complete_callback_t complete; + void *arg; + }; -- **ep** 端点信息 -- **buffer** 要发送或者读取的数据缓冲区 -- **buflen** 要发送或者接收的长度,最大不得高于 16K -- **timeout** 超时时间,单位 ms -- **return** 大于等于0 表示实际发送或者接收的长度,小于 0 表示错误 +- **pipe** 端点对应的 pipe 句柄 +- **setup** setup 请求缓冲区,端点0使用 +- **transfer_buffer** 传输的数据缓冲区 +- **transfer_buffer_length** 传输长度 +- **transfer_flags** 传输时携带的 flag +- **actual_length** 实际传输长度 +- **timeout** 传输超时时间,为 0 该函数则为非阻塞,可在中断中使用 +- **errorcode** 错误码 +- **complete** 传输完成回调函数 +- **arg** 传输完成时携带的参数 -其中小于 0 的错误码如下: +`errorcode` 可以返回以下值: .. list-table:: :widths: 30 30 @@ -253,57 +241,21 @@ usbh_ep_bulk_transfer * - ERROR CODE - desc + * - ENOMEM + - 内存不足 * - ENODEV - 设备未连接 * - EBUSY - 当前数据发送或者接收还未完成 - * - EAGAIN - - 主机一直收到 NAK 包 * - ETIMEDOUT - 数据发送或者接收超时 * - EPERM - - 主机收到 STALL 包 + - 主机收到 STALL 包或者 BABBLE * - EIO - 数据传输错误 + * - EAGAIN + - 主机一直收到 NAK 包 * - EPIPE - 数据溢出 - * - ENXIO - - 设备断开,传输中止 - -usbh_ep_intr_transfer -"""""""""""""""""""""""""""""""""""" - -``usbh_ep_intr_transfer`` 同上。 - -usbh_ep_bulk_async_transfer -"""""""""""""""""""""""""""""""""""" - -``usbh_ep_bulk_async_transfer`` 对指定端点进行批量传输,传输完成将触发指定回调函数, **此函数为异步传输**。 **此函数对用户开放**。 - -.. code-block:: C - - int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg); - -- **ep** 端点信息 -- **buffer** 要发送或者读取的数据缓冲区 -- **buflen** 要发送或者接收的长度,最大不得高于 16K -- **callback** 传输完成回调函数, **该函数最终处于中断上下文** -- **arg** 用户自定义参数 -- **return** 为 0 表示配置正常,小于0 表示错误 - -usbh_ep_intr_async_transfer -"""""""""""""""""""""""""""""""""""" - -``usbh_ep_intr_async_transfer`` 同上。 - -usb_ep_cancel -"""""""""""""""""""""""""""""""""""" - -``usb_ep_cancel`` 中止当前端点传输, **此函数不对用户开放**。 - -.. code-block:: C - - int usb_ep_cancel(usbh_epinfo_t ep); - -- **ep** 端点信息 -- **return** 为 0 表示正确,小于0 表示错误 + * - ESHUTDOWN + - 设备断开,传输中止 \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 776ecb57..6abd8e22 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,12 +8,13 @@ CherryUSB 使用指南 CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的 USB 主从协议栈。同时 CherryUSB 具有以下优点: -- 比较全面的 class 驱动,并且 class 驱动全部模板化,方便学习和自主添加 -- 树状化编程,方便理清 class 驱动与接口、端点的关系,hub、port、class 之间的关系;代码层层递进,调用关系一目了然,方便理清 usb 枚举过程和 class 驱动加载 -- 设备协议栈使用等价于 uart tx/rx dma 的使用,主机协议栈的使用等价于文件的使用 -- 标准化的 porting 接口,同时面向 ip 化编程,相同 ip 无需重复编写驱动 -- Api 少,分类清晰:dcd/hcd api、注册 api、命令回调 api -- 协议栈代码精简,内存占用极小,ip 驱动代码也做到精简,能够达到 usb 硬件理论带宽 +- 代码精简,并且内存占用极小,而且还可进一步的裁剪 +- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律 +- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类 +- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程 +- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。 +- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制 +- 能够达到 USB 硬件理论带宽 其他相关链接: