Skip to content

Commit

Permalink
docs: add vendor rst
Browse files Browse the repository at this point in the history
  • Loading branch information
sakumisu committed Dec 4, 2024
1 parent 8d2afc1 commit bfc1139
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
44 changes: 44 additions & 0 deletions docs/source/demo/usbd_vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
vendor device 驱动编写
===========================

本节主要介绍如何编写一个 vendor device 驱动。

- 首先复制一份 class/template/usbd_xxx.c 文件
- 实现以下三个回调函数,通常来说,vendor 驱动只需要实现 vendor_handler

.. code-block:: C
intf->class_interface_handler = xxx_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = xxx_notify_handler;
- 举例如下

case1 演示对于主机 IN 数据的处理,将数据拷贝到 *data 中,并指定*len 的长度。协议栈会自动发送给主机,不需要用户手动调用发送 API。

Check warning on line 18 in docs/source/demo/usbd_vendor.rst

View workflow job for this annotation

GitHub Actions / deploy

Inline emphasis start-string without end-string. [docutils]
case2 演示对于主机 OUT 数据的处理,当执行到此函数时,说明数据都已经接收完成,可以直接读取 *data 中的数据,长度为 *len。

Check warning on line 20 in docs/source/demo/usbd_vendor.rst

View workflow job for this annotation

GitHub Actions / deploy

Inline emphasis start-string without end-string. [docutils]

Check warning on line 20 in docs/source/demo/usbd_vendor.rst

View workflow job for this annotation

GitHub Actions / deploy

Inline emphasis start-string without end-string. [docutils]
.. code-block:: C
static int xxx_vendor_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_WRN("XXX Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
switch (setup->bRequest) {
case 1:
memcpy(*data, xxx, sizeof(xxx));
*len = sizeof(xxx);
case 2:
hexdump(*data, *len);
default:
USB_LOG_WRN("Unhandled XXX Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
return 0;
}
- 最后使用形如 usbd_add_interface(busid, usbd_xxx_init_intf(&intf)) 注册接口
127 changes: 127 additions & 0 deletions docs/source/demo/usbh_vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
vendor host 驱动编写
===========================

本节主要介绍如何编写一个 vendor host 驱动。

- 首先复制一份 class/template/usbh_xxx.c 文件

- 定义 class 驱动并使用 CLASS_INFO_DEFINE 前缀,这样,枚举完成后,协议栈自动通过 usbd_class_find_driver 来查找对应的驱动。

.. code-block:: C
static const struct usbh_class_driver xxx_class_driver = {
.driver_name = "xxx",
.connect = usbh_xxx_connect,
.disconnect = usbh_xxx_disconnect
};
CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
.bInterfaceClass = 0,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.id_table = NULL,
.class_driver = &xxx_class_driver
};
- 实现 connect 和 disconnect 函数, 在 connect 函数中,需要分配一个 xxx_class 结构体,在 disconnect 函数中释放 urb 和 xxx_class。

.. code-block:: C
struct usbh_xxx {
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *xxxin;
struct usb_endpoint_descriptor *xxxout;
struct usbh_urb xxxin_urb;
struct usbh_urb xxxout_urb;
uint8_t intf; /* interface number */
uint8_t minor;
void *user_data;
};
static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
{
struct usb_endpoint_descriptor *ep_desc;
int ret;
struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
if (xxx_class == NULL) {
USB_LOG_ERR("Fail to alloc xxx_class\r\n");
return -USB_ERR_NOMEM;
}
return ret;
}
static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;
if (xxx_class) {
if (xxx_class->xxxin) {
usbh_kill_urb(&xxx_class->xxxin_urb);
}
if (xxx_class->xxxout) {
usbh_kill_urb(&xxx_class->xxxout_urb);
}
if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xxx_stop(xxx_class);
}
usbh_xxx_class_free(xxx_class);
}
return ret;
}
- 初始化端点

.. code-block:: C
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(xxx_class->intin, ep_desc);
} else {
USBH_EP_INIT(xxx_class->intout, ep_desc);
}
}
- 最后设计收发 API,根据实际情况设计成同步 or 异步。

.. code-block:: C
int usbh_xxx_in_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &xxx_class->xxxin_urb;
usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxin, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
int usbh_xxx_out_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
{
int ret;
struct usbh_urb *urb = &xxx_class->xxxout_urb;
usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxout, buffer, buflen, timeout, NULL, NULL);
ret = usbh_submit_urb(urb);
if (ret == 0) {
ret = urb->actual_length;
}
return ret;
}
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
demo/usbh_net
demo/usbh_bluetooth
demo/usbh_wifi
demo/usbd_vendor
demo/usbh_vendor

.. toctree::
:maxdepth: 1
Expand Down

0 comments on commit bfc1139

Please sign in to comment.