-
Notifications
You must be signed in to change notification settings - Fork 287
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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。 | ||
case2 演示对于主机 OUT 数据的处理,当执行到此函数时,说明数据都已经接收完成,可以直接读取 *data 中的数据,长度为 *len。 | ||
Check warning on line 20 in docs/source/demo/usbd_vendor.rst GitHub Actions / deploy
|
||
.. 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)) 注册接口 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters