docs: update docs and add english version
Signed-off-by: sakumisu <1203593632@qq.com>
This commit is contained in:
BIN
docs/en/demo/img/cherryadb.png
Executable file
BIN
docs/en/demo/img/cherryadb.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
BIN
docs/en/demo/img/otg.png
Executable file
BIN
docs/en/demo/img/otg.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 466 KiB |
BIN
docs/en/demo/img/rtt_adb_shell1.png
Executable file
BIN
docs/en/demo/img/rtt_adb_shell1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
docs/en/demo/img/rtt_adb_shell2.png
Executable file
BIN
docs/en/demo/img/rtt_adb_shell2.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 497 KiB |
BIN
docs/en/demo/img/usbh_serial.png
Executable file
BIN
docs/en/demo/img/usbh_serial.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 MiB |
14
docs/en/demo/usb_otg.rst
Executable file
14
docs/en/demo/usb_otg.rst
Executable file
@@ -0,0 +1,14 @@
|
||||
USB OTG
|
||||
=================
|
||||
|
||||
If you need to use OTG functionality, first the chip you're using needs to support ID detection capability, then enable the ``CONFIG_USB_OTG_ENABLE`` macro, and replace ``usbh_initialize`` or ``usbd_initialize`` in previous examples with ``usbotg_initialize``.
|
||||
|
||||
The ID detection circuit varies depending on different USB interface types, with micro-USB and USB-C being the two common interface types.
|
||||
|
||||
- If it's a micro-USB interface, connect the ID line to the chip's ID pin and enable the ID function.
|
||||
- If it's a USB-C interface, since there's no ID pin, you need to use CC circuit to convert to ID and then connect to the chip's ID pin. A common circuit diagram is shown below (DNP means Do Not Populate):
|
||||
|
||||
.. figure:: img/otg.png
|
||||
|
||||
|
||||
.. note:: In addition to the ID pin, you also need to add VBUS output switch control. When working in host mode, enable VBUS power supply; when working in device mode, disable VBUS power supply.
|
||||
28
docs/en/demo/usbd_adb.rst
Executable file
28
docs/en/demo/usbd_adb.rst
Executable file
@@ -0,0 +1,28 @@
|
||||
ADB Device
|
||||
=================
|
||||
|
||||
The adb device demo refers to the `demo/adb/usbd_adb_template.c` template. It adapts to **cherrysh** (`platform/demo/adb/cherrysh_port.c`) and **rt-thread msh** (`platform/rtthread/usbd_adb_shell.c`) by default. You only need to add the following initialization in main.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
cherryadb_init(0, xxxxx);
|
||||
|
||||
If using rt-thread, you also need to enable adb device in menuconfig.
|
||||
|
||||
.. figure:: img/rtt_adb_shell1.png
|
||||
|
||||
Entering ADB
|
||||
--------------
|
||||
|
||||
- When using **cherrysh**, automatically enters adb mode after enumeration is completed
|
||||
- When using **msh**, you need to input ``adb_enter`` in **msh** to enter adb mode
|
||||
|
||||
Exiting ADB
|
||||
--------------
|
||||
|
||||
- When using **cherrysh**, input ``exit`` to exit adb mode
|
||||
- When using **msh**, you need to input ``adb_exit`` in **msh** to exit adb mode
|
||||
|
||||
.. figure:: img/cherryadb.png
|
||||
|
||||
.. figure:: img/rtt_adb_shell2.png
|
||||
10
docs/en/demo/usbd_audiov1.rst
Executable file
10
docs/en/demo/usbd_audiov1.rst
Executable file
@@ -0,0 +1,10 @@
|
||||
AudioV1 Device
|
||||
=================
|
||||
|
||||
UAC1 demo refers to `demo/audio_v1_*.c` template.
|
||||
|
||||
When using UAC1.0, pay attention to the following points:
|
||||
|
||||
- When using Windows, when modifying any descriptor parameters, you must synchronously modify the string descriptor and uninstall the driver, otherwise Windows will consider the device unchanged and continue to use the old driver, causing device recognition failure. Linux is not subject to this restriction.
|
||||
- Download RemoveGhostDev64.exe from the QQ group files to automatically delete all USB registered driver information, eliminating the need for the first step
|
||||
- Prohibit adding print statements and time-consuming operations in interrupts, otherwise it will affect USB transmission according to interval
|
||||
10
docs/en/demo/usbd_audiov2.rst
Executable file
10
docs/en/demo/usbd_audiov2.rst
Executable file
@@ -0,0 +1,10 @@
|
||||
AudioV2 Device
|
||||
=================
|
||||
|
||||
When using UAC2.0, please note the following points:
|
||||
|
||||
- On Windows, when modifying any parameter in the descriptor, the string descriptor must be modified synchronously and the driver must be uninstalled. Otherwise, Windows will think the device has not changed and continue to use the old driver, resulting in device recognition failure. Linux is not subject to this limitation.
|
||||
- You can download RemoveGhostDev64.exe from the QQ group files to automatically delete all USB registered driver information, eliminating the need for the first step
|
||||
- Windows 10 UAC2.0 functionality is incomplete, please use Windows 11 to test UAC2.0 functionality. Linux is not subject to this limitation
|
||||
- Windows has calculation errors in the sampling rate range setting for multi-channel (more than 2 channels). For example, if you set 8K~96K, the actual range is greater than or equal to 8K and less than 96K, not less than or equal to 96K. Linux is not subject to this limitation
|
||||
- Prohibit adding prints and time-consuming operations in interrupts, otherwise it will affect USB transmission according to interval
|
||||
104
docs/en/demo/usbd_cdc_acm.rst
Executable file
104
docs/en/demo/usbd_cdc_acm.rst
Executable file
@@ -0,0 +1,104 @@
|
||||
CDC ACM Device
|
||||
=================
|
||||
|
||||
This demo mainly demonstrates CDC ACM functionality. Reference the `demo/cdc_acm_template.c` template. Includes transmission/reception testing, DTR control, ZLP testing, and performance testing.
|
||||
|
||||
- Allocate read/write buffers for data transmission/reception. Buffers need to be modified with nocache. Here we use 2048 bytes for both read and write for subsequent ZLP testing and performance testing.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
|
||||
|
||||
|
||||
- In the protocol stack event callback, we need to start the first transmission after enumeration is complete and clear the related flags. This can be done in the reset event or in the configured event.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
static void usbd_event_handler(uint8_t busid, uint8_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
break;
|
||||
case USBD_EVENT_CONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case USBD_EVENT_RESUME:
|
||||
break;
|
||||
case USBD_EVENT_SUSPEND:
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
ep_tx_busy_flag = false;
|
||||
/* setup first out ep read transfer */
|
||||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||
break;
|
||||
case USBD_EVENT_SET_REMOTE_WAKEUP:
|
||||
break;
|
||||
case USBD_EVENT_CLR_REMOTE_WAKEUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- Continue to initiate reception in the reception complete interrupt; determine whether to send ZLP in the transmission complete interrupt.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
|
||||
// for (int i = 0; i < 100; i++) {
|
||||
// printf("%02x ", read_buffer[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
/* setup next out ep read transfer */
|
||||
usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
|
||||
}
|
||||
|
||||
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
USB_LOG_RAW("actual in len:%d\r\n", nbytes);
|
||||
|
||||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
|
||||
} else {
|
||||
ep_tx_busy_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
- The following is for testing DTR functionality and controlling USB transmission. DTR and RTS are only used in conjunction with UART; for pure USB, they are not very useful - this is just for testing. DTR switch uses any serial port host computer and check DTR.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
|
||||
{
|
||||
if (dtr) {
|
||||
dtr_enable = 1;
|
||||
} else {
|
||||
dtr_enable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- Keep calling send in the main function
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void cdc_acm_data_send_with_dtr_test(uint8_t busid)
|
||||
{
|
||||
if (dtr_enable) {
|
||||
ep_tx_busy_flag = true;
|
||||
usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
|
||||
while (ep_tx_busy_flag) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- Note that we set the length to 2048 for testing ZLP functionality. In actual use, the receive length should use CDC_MAX_MPS. See :ref:`usb_ext` for specific reasons.
|
||||
- For performance testing, use tools/test_srcipts/test_cdc_speed.py and remove the print statements in `usbd_cdc_acm_bulk_out` and `usbd_cdc_acm_bulk_in` before testing, otherwise it will affect the test results.
|
||||
|
||||
|
||||
In addition, for CDC ACM with OS, we usually use asynchronous read and store data in a ringbuffer, and use synchronous write with semaphore.
|
||||
4
docs/en/demo/usbd_ecm.rst
Executable file
4
docs/en/demo/usbd_ecm.rst
Executable file
@@ -0,0 +1,4 @@
|
||||
CDC ECM Device
|
||||
=================
|
||||
|
||||
ECM demo refers to the `demo/cdc_ecm*.c` template. By default it interfaces with lwip protocol stack, and the upper layer can use lwip api.
|
||||
4
docs/en/demo/usbd_hid.rst
Executable file
4
docs/en/demo/usbd_hid.rst
Executable file
@@ -0,0 +1,4 @@
|
||||
HID Device
|
||||
=================
|
||||
|
||||
HID functionality is relatively simple, so no detailed explanation is needed. Note that when using the HID custom example, it needs to be used with `tools/test_srcipts/test_hid_inout.py` (with report ID functionality).
|
||||
39
docs/en/demo/usbd_msc.rst
Executable file
39
docs/en/demo/usbd_msc.rst
Executable file
@@ -0,0 +1,39 @@
|
||||
MSC Device
|
||||
=================
|
||||
|
||||
This section mainly demonstrates USB mass storage device functionality. By default, RAM is used as storage medium to simulate a USB drive.
|
||||
|
||||
- Implement read/write and capacity acquisition interfaces for the USB drive. Note that the capacity block_num is virtual - there aren't actually that many blocks. Read/write data exceeding BLOCK_COUNT will be discarded.
|
||||
|
||||
block_size is generally 512/2048/4096.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
||||
{
|
||||
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||
*block_size = BLOCK_SIZE;
|
||||
}
|
||||
int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < BLOCK_COUNT)
|
||||
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (sector < BLOCK_COUNT)
|
||||
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- By default, the above APIs execute in interrupt context. If you need to execute in non-interrupt context, you can choose the following:
|
||||
|
||||
1. In bare metal, enable `CONFIG_USBDEV_MSC_POLLING` and call `usbd_msc_polling` in while1, then read/write functions execute in while1.
|
||||
|
||||
2. In OS, enable `CONFIG_USBDEV_MSC_THREAD`, then read/write functions execute in thread.
|
||||
|
||||
- Modifying `CONFIG_USBDEV_MSC_BUFSIZE` will affect U disk read/write speed. It must be an integer multiple of block_size, of course, it will also increase RAM usage.
|
||||
|
||||
- If RAM example works but doesn't work after changing medium to SD or FLASH, it must be a medium driver problem.
|
||||
6
docs/en/demo/usbd_mtp.rst
Executable file
6
docs/en/demo/usbd_mtp.rst
Executable file
@@ -0,0 +1,6 @@
|
||||
MTP Device
|
||||
=================
|
||||
|
||||
MTP demo references the `demo/mtp_template.c` template. Adapted for FatFS file system by default (`platform/fatfs/usbd_fatfs_mtp.c`).
|
||||
|
||||
.. note:: MTP is commercially charged and does not provide open source MTP driver code. Please contact official support to purchase authorization.
|
||||
4
docs/en/demo/usbd_rndis.rst
Executable file
4
docs/en/demo/usbd_rndis.rst
Executable file
@@ -0,0 +1,4 @@
|
||||
CDC RNDIS Device
|
||||
=================
|
||||
|
||||
RNDIS demo refers to `demo/cdc_rndis*.c` template. By default it interfaces with lwip protocol stack, the upper layer can use lwip api.
|
||||
44
docs/en/demo/usbd_vendor.rst
Executable file
44
docs/en/demo/usbd_vendor.rst
Executable file
@@ -0,0 +1,44 @@
|
||||
Writing Vendor Device Driver
|
||||
============================================
|
||||
|
||||
This section mainly introduces how to write a vendor device driver.
|
||||
|
||||
- First copy a class/template/usbd_xxx.c file
|
||||
- Implement the following three callback functions. Generally speaking, vendor drivers only need to implement vendor_handlerDevice 驱动编写
|
||||
|
||||
.. 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;
|
||||
|
||||
- Example as follows
|
||||
|
||||
case1 demonstrates processing of host IN data, copying data to *data and specifying the length of *len. The protocol stack will automatically send to the host without requiring users to manually call send API.
|
||||
|
||||
case2 demonstrates processing of host OUT data. When this function is executed, it means all data has been received and can directly read data from *data with length *len.
|
||||
|
||||
.. 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;
|
||||
}
|
||||
|
||||
- Finally register the interface using the form usbd_add_interface(busid, usbd_xxx_init_intf(&intf))
|
||||
83
docs/en/demo/usbd_video.rst
Executable file
83
docs/en/demo/usbd_video.rst
Executable file
@@ -0,0 +1,83 @@
|
||||
USB Video Device
|
||||
=================
|
||||
|
||||
This section mainly demonstrates USB UVC functionality, supporting YUYV, MJPEG, H264 formats. For demonstration convenience, static images are used throughout.
|
||||
|
||||
The demo includes **video_static_yuyv_template**, **video_static_mjpeg_template**, **video_static_h264_template**, with only descriptors and image data being different.
|
||||
|
||||
- In high-speed mode, the default maximum is 1024 bytes, but if the chip supports additional transactions, it can be configured up to 2048 bytes or 3072 bytes, which can improve transmission efficiency.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#define MAX_PAYLOAD_SIZE 1024 // for high speed with one transcations every one micro frame
|
||||
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
||||
|
||||
// #define MAX_PAYLOAD_SIZE 2048 // for high speed with two transcations every one micro frame
|
||||
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11))
|
||||
|
||||
// #define MAX_PAYLOAD_SIZE 3072 // for high speed with three transcations every one micro frame
|
||||
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
|
||||
|
||||
#else
|
||||
#define MAX_PAYLOAD_SIZE 1020
|
||||
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
||||
#endif
|
||||
|
||||
- Usually only need to modify WIDTH and HEIGHT
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#define WIDTH (unsigned int)(640)
|
||||
#define HEIGHT (unsigned int)(480)
|
||||
|
||||
#define CAM_FPS (30)
|
||||
#define INTERVAL (unsigned long)(10000000 / CAM_FPS)
|
||||
#define MIN_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
|
||||
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
|
||||
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
|
||||
|
||||
- USB endpoint configuration, default interval is 1, which is 1ms in full-speed mode and 125us in high-speed mode. Synchronization type uses asynchronous mode.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
|
||||
|
||||
|
||||
- Use `usbd_video_stream_start_write` to transfer data. The final **do_copy** option indicates whether to copy data to packet_buffer.
|
||||
If copy is not selected, header information will be directly filled in the original image data and sent directly, achieving zero copy functionality.
|
||||
|
||||
- Because static data is provided and cannot be modified, a new frame_buffer needs to be allocated for image transmission. In actual camera integration scenarios, dynamic data is used and the camera's data buffer can be used directly.
|
||||
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if (usbd_video_stream_split_transfer(busid, ep)) {
|
||||
/* one frame has done */
|
||||
iso_tx_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[32 * 1024];
|
||||
|
||||
void video_test(uint8_t busid)
|
||||
{
|
||||
memset(packet_buffer, 0, sizeof(packet_buffer));
|
||||
|
||||
while (1) {
|
||||
if (tx_flag) {
|
||||
iso_tx_busy = true;
|
||||
memcpy(frame_buffer, cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); // cherryusb_mjpeg is a static MJPEG frame buffer, so we need copy it to frame_buffer
|
||||
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)frame_buffer, sizeof(cherryusb_mjpeg), false);
|
||||
while (iso_tx_busy) {
|
||||
if (tx_flag == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
docs/en/demo/usbd_webusb.rst
Executable file
21
docs/en/demo/usbd_webusb.rst
Executable file
@@ -0,0 +1,21 @@
|
||||
WebUSB Device
|
||||
=================
|
||||
|
||||
This demo mainly demonstrates webusb functionality. Webusb is mainly used to pop up web pages and access USB devices. The example uses webusb_hid_template.c.
|
||||
|
||||
- When registering descriptors, just register BOS, MSOSV2, WEBUSB descriptors.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||
usbd_webusb_desc_register(busid, &webusb_url_desc);
|
||||
|
||||
- Add an interface descriptor for webusb
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00)
|
||||
|
||||
- The rest use hid descriptors, no further elaboration
|
||||
- After enumeration is completed, webpage information will pop up in the lower right corner of the computer, click to open the webpage
|
||||
55
docs/en/demo/usbd_winusb.rst
Executable file
55
docs/en/demo/usbd_winusb.rst
Executable file
@@ -0,0 +1,55 @@
|
||||
WinUSB Device
|
||||
=================
|
||||
|
||||
This section mainly introduces the winusb driver. Winusb is a general driver provided by Windows to allow users to access USB custom class devices in a user-friendly manner. It is essentially CDC ACM, but without baud rate setting commands.
|
||||
WINUSB versions are divided into V1/V2 versions according to USB versions. V2 version requires BOS descriptor, while V1 version does not. **V2 version requires setting USB2.1 version number in device descriptor**.
|
||||
|
||||
.. note:: Changing any winusb descriptor configuration may result in successful enumeration but inability to recognize the device. You need to delete all registry entries under Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags, then unplug and replug the device to take effect.
|
||||
|
||||
- V1 version descriptor registration
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
const struct usb_descriptor winusbv1_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback,
|
||||
.msosv1_descriptor = &msosv1_desc
|
||||
};
|
||||
|
||||
OR
|
||||
|
||||
usbd_msosv1_desc_register(busid, &msosv1_desc);
|
||||
|
||||
- V2 version descriptor registration
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
const struct usb_descriptor winusbv2_descriptor = {
|
||||
.device_descriptor_callback = device_descriptor_callback,
|
||||
.config_descriptor_callback = config_descriptor_callback,
|
||||
.device_quality_descriptor_callback = device_quality_descriptor_callback,
|
||||
.string_descriptor_callback = string_descriptor_callback,
|
||||
.msosv2_descriptor = &msosv2_desc,
|
||||
.bos_descriptor = &bos_desc,
|
||||
};
|
||||
|
||||
OR
|
||||
|
||||
usbd_bos_desc_register(busid, &bos_desc);
|
||||
usbd_msosv2_desc_register(busid, &msosv2_desc);
|
||||
|
||||
|
||||
- Interface descriptor registration
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
/* Interface 0 */
|
||||
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
|
||||
/* Endpoint OUT 2 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||
/* Endpoint IN 1 */
|
||||
USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
|
||||
|
||||
- Read and write operations are the same as CDC ACM, no further elaboration
|
||||
4
docs/en/demo/usbh_audio.rst
Executable file
4
docs/en/demo/usbh_audio.rst
Executable file
@@ -0,0 +1,4 @@
|
||||
Audio Host
|
||||
=================
|
||||
|
||||
.. note:: Host UAC is commercially charged. Please contact the official for purchase authorization.
|
||||
2
docs/en/demo/usbh_bluetooth.rst
Executable file
2
docs/en/demo/usbh_bluetooth.rst
Executable file
@@ -0,0 +1,2 @@
|
||||
BTBLE Host
|
||||
=================
|
||||
55
docs/en/demo/usbh_hid.rst
Executable file
55
docs/en/demo/usbh_hid.rst
Executable file
@@ -0,0 +1,55 @@
|
||||
HID Host
|
||||
=================
|
||||
|
||||
This section mainly introduces the use of Host HID class.
|
||||
|
||||
- Create a one-time thread in HID enumeration completion callback
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
|
||||
void usbh_hid_run(struct usbh_hid *hid_class)
|
||||
{
|
||||
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class);
|
||||
}
|
||||
|
||||
void usbh_hid_stop(struct usbh_hid *hid_class)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
- Here we use the asynchronous operation of usbh_submit_urb, process data in interrupt and continue to receive next data.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
static void usbh_hid_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)argument;
|
||||
;
|
||||
|
||||
/* test with only one buffer, if you have more hid class, modify by yourself */
|
||||
|
||||
/* Suggest you to use timer for int transfer and use ep interval */
|
||||
usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_buffer, hid_class->intin->wMaxPacketSize, 0, usbh_hid_callback, hid_class);
|
||||
ret = usbh_submit_urb(&hid_class->intin_urb);
|
||||
if (ret < 0) {
|
||||
goto delete;
|
||||
}
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
- Of course, you can also not use asynchronous operations, but use synchronous operations with timeout.
|
||||
- HID uses interrupt transfer, so normally we need to set a timer based on **bInterval** to trigger interrupt transfer at regular intervals. This is not used in the demo. If you have precise time requirements, you can choose to use a timer to trigger asynchronous sending.
|
||||
- Taking hub communication as an example, a one-time timer is used, but a periodic timer can also be used.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed) / 1000, hub_int_timeout, hub, 0);
|
||||
|
||||
.. note::
|
||||
|
||||
Here `USBH_GET_URB_INTERVAL` is a macro definition used to calculate the URB transfer interval time based on binterval. The unit is us, while the timer minimum is ms, so it needs to be divided by 1000. For intervals less than or equal to 1ms, no timer is needed.
|
||||
56
docs/en/demo/usbh_msc.rst
Executable file
56
docs/en/demo/usbh_msc.rst
Executable file
@@ -0,0 +1,56 @@
|
||||
MSC Host
|
||||
=================
|
||||
|
||||
This section mainly introduces the use of Host MSC. Read and write functions are implemented with the help of FATFS.
|
||||
|
||||
- Register a thread in the callback after MSC enumeration is completed, used for read and write operations.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbh_msc_run(struct usbh_msc *msc_class)
|
||||
{
|
||||
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
|
||||
}
|
||||
|
||||
void usbh_msc_stop(struct usbh_msc *msc_class)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
- Without using fatfs, directly use usbh_msc_scsi_read10 or usbh_msc_scsi_write10 functions for read and write operations.
|
||||
- If using fatfs, you need to call fatfs interfaces in usbh_msc_thread for read and write operations. For MSC read/write adaptation to fatfs, refer to `platform/fatfs/usbh_fatfs.c`
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
static void usbh_msc_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
struct usbh_msc *msc_class = (struct usbh_msc *)argument;
|
||||
|
||||
/* test with only one buffer, if you have more msc class, modify by yourself */
|
||||
#if 1
|
||||
/* get the partition table */
|
||||
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||
goto delete;
|
||||
}
|
||||
for (uint32_t i = 0; i < 512; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||
}
|
||||
USB_LOG_RAW("\r\n");
|
||||
#endif
|
||||
|
||||
#if TEST_USBH_MSC_FATFS
|
||||
usb_msc_fatfs_test();
|
||||
#endif
|
||||
// clang-format off
|
||||
delete:
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
- Finally, after processing is completed or failed, delete the thread.
|
||||
167
docs/en/demo/usbh_net.rst
Executable file
167
docs/en/demo/usbh_net.rst
Executable file
@@ -0,0 +1,167 @@
|
||||
Network Host
|
||||
=================
|
||||
|
||||
This section mainly introduces the use of Host USB network cards. The following USB ne- Because the USB network card has been internally connected to LWIP, users can directly use LWIP APIs without worrying about USB implementation.
|
||||
|
||||
USB Network Card LWIP Configuration Macro Related Notes
|
||||
-----------------------------------------------------------
|
||||
|
||||
**LWIP_TCPIP_CORE_LOCKING_INPUT** is used to not use lwip built-in tcpip thread, but use USB's own receive processing thread.
|
||||
|
||||
**LWIP_TCPIP_CORE_LOCKING** is enabled by default in current lwip versions, and it is also recommended to be mandatory.
|
||||
|
||||
**PBUF_POOL_BUFSIZE** is recommended to be greater than 1600, used with LWIP_TCPIP_CORE_LOCKING_INPUT, because we provide zero copy method using static pbuf instead of copying data into pbuf.
|
||||
|
||||
**TCPIP_THREAD_STACKSIZE** is recommended to be greater than 1K to prevent stack overflow.are currently supported and tested:
|
||||
|
||||
- 4G network cards: EC20(ECM/RNDIS), mobile phones (RNDIS), SIMCOM7600(RNDIS), ML307R(RNDIS), AIR780(RNDIS)
|
||||
|
||||
.. caution:: Please note that some 4G network cards do not have auto-dial functionality by default. Please replace the firmware or use AT commands to configure auto-dial, otherwise you cannot get an IP.
|
||||
|
||||
- USB Ethernet cards: ASIX AX88772, REALTEK RTL8152
|
||||
- USB WIFI cards: Bouffalo Lab BL616 (RNDIS/ECM)
|
||||
|
||||
USB Network Card Related Macros and Files
|
||||
--------------------------------------------------
|
||||
|
||||
The network card related macros are as follows, mainly used to register network card drivers according to different network components:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
// #define CONFIG_USBHOST_PLATFORM_CDC_ECM
|
||||
// #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
|
||||
// #define CONFIG_USBHOST_PLATFORM_CDC_NCM
|
||||
// #define CONFIG_USBHOST_PLATFORM_ASIX
|
||||
// #define CONFIG_USBHOST_PLATFORM_RTL8152
|
||||
|
||||
.. note:: If Kconfig system is used, the above macros are automatically generated. For other platforms, please define manually.
|
||||
|
||||
USB network card transmission layer has been connected to relevant network components, listed as follows:
|
||||
|
||||
- Custom OS + LWIP please use **platform/lwip/usbh_lwip.c**, need to include this file yourself and enable the above relevant macros. Call `tcpip_init(NULL, NULL)` before initializing USB
|
||||
- RT-THREAD + LWIP please use **platform/rtthread/usbh_lwip.c**, automatically select this file after enabling corresponding network card driver in Kconfig, automatically call `tcpip_init(NULL, NULL)` after selecting rt-thread lwip
|
||||
- ESP-IDF + LWIP please use **platform/freertos/usbh_net.c**, automatically select this file after enabling corresponding network card driver in Kconfig, and call `esp_netif_init()` + `esp_event_loop_create_default()` before initializing USB
|
||||
- NUTTX + NUTTX network component please use **platform/nuttx/usbh_net.c**, automatically select this file after enabling corresponding network card driver in Kconfig, automatically call after selecting network component
|
||||
|
||||
.. note:: If adding code yourself, don't forget to add USB network card driver related source files, such as **class/usbh_cdc_ecm.c**. So we recommend using with corresponding platforms to save the trouble of adding files yourself
|
||||
|
||||
USB Network Card Connection Process
|
||||
---------------------------------------------
|
||||
|
||||
The following example shows the LWIP connection process.
|
||||
|
||||
- After USB network card enumeration is completed, the `usbh_xxx_run` function will be **automatically** called, at which time netif driver is registered, and DHCP client and IP acquisition timer are started.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
|
||||
netif->hwaddr_len = 6;
|
||||
memcpy(netif->hwaddr, cdc_ecm_class->mac, 6);
|
||||
|
||||
IP4_ADDR(&g_ipaddr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&g_netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&g_gateway, 0, 0, 0, 0);
|
||||
|
||||
netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input);
|
||||
netif_set_default(netif);
|
||||
while (!netif_is_up(netif)) {
|
||||
}
|
||||
|
||||
dhcp_handle = usb_osal_timer_create("dhcp", 200, dhcp_timeout, netif, true);
|
||||
if (dhcp_handle == NULL) {
|
||||
USB_LOG_ERR("timer creation failed! \r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL);
|
||||
#if LWIP_DHCP
|
||||
dhcp_start(netif);
|
||||
usb_osal_timer_start(dhcp_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
- `usbh_lwip_eth_output_common` is used to assemble transmitted pbuf into USB network card data packets
|
||||
- `usbh_lwip_eth_input_common` is used to assemble USB network card data into pbuf
|
||||
- Actual network card transmission and reception processing
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
static err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
int ret;
|
||||
(void)netif;
|
||||
|
||||
usbh_lwip_eth_output_common(p, usbh_cdc_ecm_get_eth_txbuf());
|
||||
ret = usbh_cdc_ecm_eth_output(p->tot_len);
|
||||
if (ret < 0) {
|
||||
return ERR_BUF;
|
||||
} else {
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen)
|
||||
{
|
||||
usbh_lwip_eth_input_common(&g_cdc_ecm_netif, buf, buflen);
|
||||
}
|
||||
|
||||
- After the USB network card is unplugged, the `usbh_xxx_stop` function will be **automatically** called, at which time you need to stop the DHCP client, delete the timer, and remove the netif.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void usbh_cdc_ecm_stop(struct usbh_cdc_ecm *cdc_ecm_class)
|
||||
{
|
||||
struct netif *netif = &g_cdc_ecm_netif;
|
||||
(void)cdc_ecm_class;
|
||||
|
||||
#if LWIP_DHCP
|
||||
dhcp_stop(netif);
|
||||
dhcp_cleanup(netif);
|
||||
usb_osal_timer_delete(dhcp_handle);
|
||||
#endif
|
||||
netif_set_down(netif);
|
||||
netif_remove(netif);
|
||||
}
|
||||
|
||||
- Because the USB network card has been internally connected to LWIP, users can directly use LWIP APIs without worrying about USB implementation.
|
||||
|
||||
USB Network Card LWIP Configuration Macro Related Notes
|
||||
--------------------------------------------------------------
|
||||
|
||||
**LWIP_TCPIP_CORE_LOCKING_INPUT** is used to not use lwip built-in tcpip thread, but use USB's own receive processing thread.
|
||||
|
||||
**LWIP_TCPIP_CORE_LOCKING** is enabled by default in current lwip versions, and it is also recommended to be mandatory.
|
||||
|
||||
**PBUF_POOL_BUFSIZE** is recommended to be greater than 1600, used with LWIP_TCPIP_CORE_LOCKING_INPUT, because we provide zero copy method using static pbuf instead of copying data into pbuf.
|
||||
|
||||
**TCPIP_THREAD_STACKSIZE** is recommended to be greater than 1K to prevent stack overflow.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT != 1
|
||||
#warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread
|
||||
#endif
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING != 1
|
||||
#error must set LWIP_TCPIP_CORE_LOCKING to 1
|
||||
#endif
|
||||
|
||||
#if PBUF_POOL_BUFSIZE < 1600
|
||||
#error PBUF_POOL_BUFSIZE must be larger than 1600
|
||||
#endif
|
||||
|
||||
#if TCPIP_THREAD_STACKSIZE < 1024
|
||||
#error TCPIP_THREAD_STACKSIZE must be >= 1024
|
||||
#endif
|
||||
|
||||
|
||||
Summary
|
||||
--------------
|
||||
|
||||
.. note:: Through the above content, we can see that CherryUSB's support for USB network cards is very comprehensive. Users only need to enable corresponding macros or check options to achieve automatic recognition and driver registration of USB network cards, without manually initializing network card related configurations. Users only need to focus on the application layer, which greatly facilitates user usage.
|
||||
|
||||
For specific porting articles, please refer to developers' notes https://club.rt-thread.org/ask/article/5cf3e9e0b2d95800.html
|
||||
196
docs/en/demo/usbh_serial.rst
Executable file
196
docs/en/demo/usbh_serial.rst
Executable file
@@ -0,0 +1,196 @@
|
||||
Serial Host
|
||||
=================
|
||||
|
||||
This section mainly introduces the usage of the Host serial framework. The Serial framework currently supports CDC ACM, FTDI, CP210x, CH34x, PL2303, and GSM drivers.
|
||||
|
||||
.. figure:: img/usbh_serial.png
|
||||
|
||||
Currently supports two usage methods: one is using native CherryUSB usbhost serial API for operations, and the other is based on platform-wrapped APIs such as RT-Thread device API and NuttX POSIX API.
|
||||
|
||||
The following demonstrates using CherryUSB usbhost serial API for serial loopback testing with blocking transmission and asynchronous reception:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct usbh_serial *serial;
|
||||
|
||||
serial = usbh_serial_open("/dev/ttyACM0", USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
|
||||
if (serial == NULL) {
|
||||
serial = usbh_serial_open("/dev/ttyUSB0", USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
|
||||
if (serial == NULL) {
|
||||
USB_LOG_RAW("no serial device found\r\n");
|
||||
goto delete;
|
||||
}
|
||||
}
|
||||
|
||||
struct usbh_serial_termios termios;
|
||||
|
||||
memset(&termios, 0, sizeof(termios));
|
||||
termios.baudrate = 115200;
|
||||
termios.stopbits = 0;
|
||||
termios.parity = 0;
|
||||
termios.databits = 8;
|
||||
termios.rtscts = false;
|
||||
termios.rx_timeout = 0;
|
||||
ret = usbh_serial_control(serial, USBH_SERIAL_CMD_SET_ATTR, &termios);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("set serial attr error, ret:%d\r\n", ret);
|
||||
goto delete_with_close;
|
||||
}
|
||||
|
||||
serial_tx_bytes = 0;
|
||||
while (1) {
|
||||
ret = usbh_serial_write(serial, serial_tx_buffer, sizeof(serial_tx_buffer));
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("serial write error, ret:%d\r\n", ret);
|
||||
goto delete_with_close;
|
||||
} else {
|
||||
serial_tx_bytes += ret;
|
||||
|
||||
if (serial_tx_bytes == SERIAL_TEST_LEN) {
|
||||
USB_LOG_RAW("send over\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint32_t wait_timeout = 0;
|
||||
serial_rx_bytes = 0;
|
||||
while (1) {
|
||||
ret = usbh_serial_read(serial, &serial_rx_data[serial_rx_bytes], SERIAL_TEST_LEN - serial_rx_bytes);
|
||||
if (ret < 0) {
|
||||
USB_LOG_RAW("serial read error, ret:%d\r\n", ret);
|
||||
goto delete_with_close;
|
||||
} else {
|
||||
serial_rx_bytes += ret;
|
||||
|
||||
if (serial_rx_bytes == SERIAL_TEST_LEN) {
|
||||
USB_LOG_RAW("receive over\r\n");
|
||||
for (uint32_t i = 0; i < SERIAL_TEST_LEN; i++) {
|
||||
if (serial_rx_data[i] != 0xa5) {
|
||||
USB_LOG_RAW("serial loopback data error at index %d, data: 0x%02x\r\n", (unsigned int)i, serial_rx_data[i]);
|
||||
goto delete_with_close;
|
||||
}
|
||||
}
|
||||
serial_test_success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
wait_timeout++;
|
||||
|
||||
if (wait_timeout > 500) { // 5s
|
||||
USB_LOG_RAW("serial read timeout\r\n");
|
||||
goto delete_with_close;
|
||||
}
|
||||
|
||||
usb_osal_msleep(10);
|
||||
}
|
||||
|
||||
usbh_serial_close(serial);
|
||||
|
||||
.. caution:: Note that the example uses a simple send-then-read approach, so the total length sent cannot exceed CONFIG_USBHOST_SERIAL_RX_SIZE. For normal TX/RX usage, please perform them separately.
|
||||
|
||||
Users need to consider the following three scenarios:
|
||||
|
||||
- USB2TTL device + baud rate enabled (USB2TTL devices must enable baud rate), in this case you need to use `usbh_serial_write` and `usbh_serial_read` to send and receive data, **and read operations need to be timely to prevent ringbuf data overflow and packet loss**. Cannot use `usbh_serial_cdc_write_async` and `usbh_serial_cdc_read_async`
|
||||
|
||||
- Pure USB device + baud rate not started, in this case you can use `usbh_serial_cdc_write_async` and `usbh_serial_cdc_read_async` for asynchronous send/receive data. For blocking, you can use `usbh_serial_write`, but cannot use `usbh_serial_read`.
|
||||
|
||||
- Pure USB device + baud rate started, same as 1, but the reception rate will be discounted (because of an extra layer of ringbuf). In this case, `usbh_serial_cdc_write_async` and `usbh_serial_cdc_read_async` cannot be used either. **If it is a GSM device, please use the first scenario**.
|
||||
|
||||
.. note:: Simply put, if receiving data requires going through a ringbuf layer, please use the first scenario.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
|
||||
[I/usbh_core] New device found,idVendor:10c4,idProduct:ea60,bcdDevice:0100
|
||||
[I/usbh_core] The device has 1 bNumConfigurations
|
||||
[I/usbh_core] The device has 1 interfaces
|
||||
[I/usbh_core] Enumeration success, start loading class driver
|
||||
[I/usbh_core] Loading cp210x class driver on interface 0
|
||||
[I/usbh_cp210x] chip partnum: 0x02
|
||||
[I/usbh_cp210x] ulAmountInInQueue: 0, ulAmountInOutQueue: 0
|
||||
[I/usbh_serial] Ep=81 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=01 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (cp210x)
|
||||
start serial loopback test, len: 1024
|
||||
send over
|
||||
receive over
|
||||
serial loopback test success
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (cp210x)
|
||||
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
|
||||
[I/usbh_hub] New high-speed device on Bus 0, Hub 1, Port 1 connected
|
||||
[I/usbh_core] New device found,idVendor:0403,idProduct:6010,bcdDevice:0700
|
||||
[I/usbh_core] The device has 1 bNumConfigurations
|
||||
[I/usbh_core] The device has 2 interfaces
|
||||
[I/usbh_core] Enumeration success, start loading class driver
|
||||
[I/usbh_core] Loading ftdi class driver on interface 0
|
||||
[I/usbh_ftdi] chip name: FT2232H
|
||||
[I/usbh_serial] Ep=81 Attr=02 Mps=512 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=02 Attr=02 Mps=512 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (ftdi)
|
||||
[I/usbh_core] Loading ftdi class driver on interface 1
|
||||
[I/usbh_ftdi] chip name: FT2232H
|
||||
[I/usbh_serial] Ep=83 Attr=02 Mps=512 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=04 Attr=02 Mps=512 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyUSB1 (ftdi)
|
||||
start serial loopback test, len: 1024
|
||||
send over
|
||||
receive over
|
||||
serial loopback test success
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (ftdi)
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB1 (ftdi)
|
||||
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
|
||||
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
|
||||
[I/usbh_core] New device found,idVendor:067b,idProduct:2303,bcdDevice:0300
|
||||
[I/usbh_core] The device has 1 bNumConfigurations
|
||||
[I/usbh_core] The device has 1 interfaces
|
||||
[I/usbh_core] Enumeration success, start loading class driver
|
||||
[I/usbh_core] Loading pl2303 class driver on interface 0
|
||||
[I/usbh_pl2303] Ep=81 Attr=03 Mps=10 Interval=01 Mult=00
|
||||
[I/usbh_pl2303] chip type: PL2303HX
|
||||
[I/usbh_serial] Ep=02 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=83 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (pl2303)
|
||||
start serial loopback test, len: 1024
|
||||
send over
|
||||
receive over
|
||||
serial loopback test success
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (pl2303)
|
||||
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
|
||||
[W/usbh_hub] Failed to enable port 1
|
||||
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
|
||||
[I/usbh_core] New device found,idVendor:1a86,idProduct:7523,bcdDevice:0264
|
||||
[I/usbh_core] The device has 1 bNumConfigurations
|
||||
[I/usbh_core] The device has 1 interfaces
|
||||
[I/usbh_core] Enumeration success, start loading class driver
|
||||
[I/usbh_core] Loading ch34x class driver on interface 0
|
||||
[I/usbh_ch43x] Ep=81 Attr=03 Mps=8 Interval=01 Mult=00
|
||||
[I/usbh_ch43x] chip version: 0x31
|
||||
[I/usbh_serial] Ep=82 Attr=02 Mps=32 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=02 Attr=02 Mps=32 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyUSB0 (ch34x)
|
||||
start serial loopback test, len: 1024
|
||||
send over
|
||||
receive over
|
||||
serial loopback test success
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyUSB0 (ch34x)
|
||||
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
|
||||
[I/usbh_hub] New full-speed device on Bus 0, Hub 1, Port 1 connected
|
||||
[I/usbh_core] New device found,idVendor:42bf,idProduct:b210,bcdDevice:0217
|
||||
[I/usbh_core] The device has 1 bNumConfigurations
|
||||
[I/usbh_core] The device has 3 interfaces
|
||||
[I/usbh_core] Enumeration success, start loading class driver
|
||||
[E/usbh_core] Do not support Class:0xff, Subclass:0x01, Protocl:0x00 on interface 0
|
||||
[I/usbh_core] Loading cdc_acm class driver on interface 1
|
||||
[I/usbh_cdc_acm] Ep=85 Attr=03 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=04 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Ep=83 Attr=02 Mps=64 Interval=00 Mult=00
|
||||
[I/usbh_serial] Register Serial Class: /dev/ttyACM0 (cdc_acm)
|
||||
[I/usbh_core] Loading cdc_data class driver on interface 2
|
||||
start serial loopback test, len: 1024
|
||||
send over
|
||||
receive over
|
||||
serial loopback test success
|
||||
[I/usbh_serial] Unregister Serial Class: /dev/ttyACM0 (cdc_acm)
|
||||
[I/usbh_core] Device on Bus 0, Hub 1, Port 1 disconnected
|
||||
|
||||
127
docs/en/demo/usbh_vendor.rst
Executable file
127
docs/en/demo/usbh_vendor.rst
Executable file
@@ -0,0 +1,127 @@
|
||||
Writing Vendor Host Driver
|
||||
============================================
|
||||
|
||||
This section mainly introduces how to write a vendor host driver.
|
||||
|
||||
- First copy a class/template/usbh_xxx.c file
|
||||
|
||||
- Define class driver and use CLASS_INFO_DEFINE prefix, so that after enumeration is completed, the protocol stack automatically finds the corresponding driver through 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
|
||||
};
|
||||
|
||||
|
||||
- Implement connect and disconnect functions. In the connect function, you need to allocate an xxx_class structure. In the disconnect function, release the urb and 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;
|
||||
}
|
||||
|
||||
- Initialize endpoints
|
||||
|
||||
.. 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);
|
||||
}
|
||||
}
|
||||
|
||||
- Finally design send/receive APIs, design them as synchronous or asynchronous according to actual conditions.
|
||||
|
||||
.. 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;
|
||||
}
|
||||
4
docs/en/demo/usbh_video.rst
Executable file
4
docs/en/demo/usbh_video.rst
Executable file
@@ -0,0 +1,4 @@
|
||||
Video Host
|
||||
=================
|
||||
|
||||
.. note:: Host UVC is commercially charged. Please contact official support to purchase authorization.
|
||||
2
docs/en/demo/usbh_wifi.rst
Executable file
2
docs/en/demo/usbh_wifi.rst
Executable file
@@ -0,0 +1,2 @@
|
||||
WIFI Host
|
||||
=================
|
||||
Reference in New Issue
Block a user