{"id":1625,"date":"2026-02-13T05:05:15","date_gmt":"2026-02-13T04:05:15","guid":{"rendered":"https:\/\/www.skynext.tech\/?p=1625"},"modified":"2026-02-13T15:49:11","modified_gmt":"2026-02-13T14:49:11","slug":"usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux","status":"publish","type":"post","link":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/","title":{"rendered":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux."},"content":{"rendered":"\n<p>A substantial advantage of the Arduino Due MCU is the native USB High Speed interface allowing up to 480 Mbps transfers. Another option are the costlier Teensy boards that are really mature and provide a solid framework for USB bulk endpoints data interfaces not limited to ttyACM Serial over USB interfaces. However, it is absolutely possible to integrate a vendor (custom) bulk pair of endpoints (IN and OUT) on Arduino Due, it&#8217;s just that there is not much documentation besides examples such as the MIDI USB library and articles about it.<\/p>\n\n\n\n<p>In this article, we leveraged the power of LLMs advices and validated them through testing to add support for an additional pair of endpoints, such that the native SerialUSB object could still be used (for telemetry, communication control or debugging)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Incentive.<\/h2>\n\n\n\n<p>Using a custom pair of endpoints has several advantages over SerialUSB.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>They can be tweaked on the MCU so as to be adapted to the maximum required transfer rate, such as number of BANKs used (up to 3) and NBTRANS.<\/li>\n\n\n\n<li>On the host side, since the endpoints are not claimed by the OS Serial over USB driver, transfers are more straightforward and do not suffer from the long chain of complex buffers used by the driver and the ttyACM stack. Interfacing can be done in user space using libusb.<\/li>\n\n\n\n<li>No tty re-configuring issues, (such as special character handling, line discipline, throttling, etc) Note that tty were historically made for terminals and text, not binary data transfers)<\/li>\n<\/ul>\n\n\n\n<p>On the downside, detection of host ready or not conditions can be different or tricker than ttyACM, as the linestate logic (DTR emulation) is not present on a custom bulk interface. The idea is thus to keep the Serial USB link for telemetry, control, and debugging, and initiate data transfer once the proper Serial USB transmission. Note that on linux detecting a DTR down condition on SerialUSB does not seem to work as well as on MS Windows from a MCU use case perspective, This all situation needs unfortunately to resort to watchdogs to re-establish a broken connection when the host is electrically connected. but not listening.<\/p>\n\n\n\n<p>Also ttyACM or the tty stack seem to behave on linux so as to limit to 64 bytes max the data fetched fro; each read() call on the port. Since USB 2.0 max packet size is 512 byte, libusb allows more efficient call economy, although the mechanism is largely different, since IO read calls are not used, but library specific &#8220;transfer submits&#8221;.<\/p>\n\n\n\n<p>In our case, the packet size is 96 byte. All writes to USB from the MCU sides will be 96 byte. Note that packet sizes and URB sizes, ZLP (zero length packets) and libusb &#8220;transfer&#8221; sizes concepts are important as understanding and managing them properly can save you a lot of headaches.<\/p>\n\n\n\n<p>libusb also has a quite steep learning curve. However, through LLM assistance, we successfully made such an interface.<\/p>\n\n\n\n<p>Note that for &#8220;real time&#8221; transfers or transfers with timing constraints (continuous flow) a separate FIFO (sched_fifo) thread is preferable on the host side. This will be shown in that example.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The MCU code.<\/h2>\n\n\n\n<p>Optimized for 1 to 4 MB\/s transfers.<\/p>\n\n\n\n<p>The latest Arduino Due (SAM) framework available in Arduino IDE and Platform IO provide helper objects (Pluggable USB), defines \/ macros to help in creating additional endpoints.<\/p>\n\n\n\n<p>First we will need some defines that will setup USB endpoint types configuration bitmasks. Here comes the first versatile configuration as these elements are not exposed for the SerialUSB interface.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly> #define EP_TYPE_BULK_IN_DATA           USB_ENDPOINT_TYPE_BULK | UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | USB_ENDPOINT_IN(0) | UOTGHS_DEVEPTCFG_EPBK_2_BANK  | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC;\n  #define EP_TYPE_BULK_OUT_DATA          USB_ENDPOINT_TYPE_BULK | UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | USB_ENDPOINT_OUT(0) | UOTGHS_DEVEPTCFG_EPBK_1_BANK  | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC;\n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">EP_TYPE_BULK_IN_DATA<\/span><span style=\"color: #5E81AC\">           USB_ENDPOINT_TYPE_BULK | UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | USB_ENDPOINT_IN(0) | UOTGHS_DEVEPTCFG_EPBK_2_BANK  | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC\">  <\/span><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">EP_TYPE_BULK_OUT_DATA<\/span><span style=\"color: #5E81AC\">          USB_ENDPOINT_TYPE_BULK | UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | USB_ENDPOINT_OUT(0) | UOTGHS_DEVEPTCFG_EPBK_1_BANK  | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | UOTGHS_DEVEPTCFG_ALLOC;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Note that we use max packet size of 512 byte, which is the maximum allowed by the USB 2.0 High speed standard. <strong>EPBK_n_BANK<\/strong> and <strong>NBTRANS_p_TRANS<\/strong> admit n and p values up to 3, at the expense of more MCU SRAM used, depending on the throughput required they can be increased and profiled for best performance.<\/p>\n\n\n\n<p>It should be known that <strong>EPBK_n_BANK<\/strong> consumes a limited amount of memory available (max 4KB), In the above case, n = 1 consumes 512 bytes. Reaching the hard limit is easy, as the total number of endpoints provided by all interfaces has to be taken into account.<\/p>\n\n\n\n<p>Note that the IN and OUT endpoints are from the reference point of the host (the computer in that case) so a IN endpoint is used to send data <strong>from<\/strong> the MCU <strong>to<\/strong> the computer.<\/p>\n\n\n\n<p>Then we need to do some class inheritance magic to extend the PluggableUSB module base class and implement our custom calls that will be used for enumeration and communication setup as well as data transfers.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>class DataBulk_: public PluggableUSBModule {\n  public:\n    DataBulk_();\n  \n    \/\/uint32_t available();\n    uint32_t write(void *buf, size_t len);\n  \n  protected:\n    virtual bool setup(USBSetup &amp;setup) override;\n    virtual int getInterface(uint8_t *interfaceCount) override;\n    virtual int getDescriptor(USBSetup &amp;setup) override;\n    virtual uint8_t getShortName(char *name) override;\n  \n  private:  \n    uint32_t epType&#91;2&#93;;\n  };\n\nbool DataBulk_::setup(USBSetup&amp; setup)\n{\n\tif (pluggedInterface != setup.wIndex) {\n\t\treturn false;\n\t}\n\n\tuint8_t request = setup.bRequest;\n\tuint8_t requestType = setup.bmRequestType;\n\t\n\t\tif (requestType &amp; REQUEST_RECIPIENT)\n\t{\n\t\tif (request == GET_INTERFACE) {\n\t\t\t\/\/ TODO: HID_GetReport();\n      uint8_t alternate_setting = 0;\n      USBD_SendControl(0,&amp;alternate_setting,sizeof(alternate_setting));\n\t\t\treturn true;\n\t\t}\n\t\tif (request == SET_INTERFACE) {\n\t\t\t\/\/ TODO: Send8(protocol);\n\t\t\treturn true;\n\t\t}\n\n\t}\n\n  return false;\n\n}\n\nint DataBulk_::getDescriptor(USBSetup&amp; setup)\n{\n\t\/\/ Check if this is a Class Descriptor request\n\tif (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }\n\tif (setup.bRequest != GET_DESCRIPTOR) { return 0; }\n\n  uint8_t desc[] =\n  {\n    \/\/interface descriptor\n    9, \/\/ bLength\n    4, \/\/ bDescriptorType = INTERFACE\n    pluggedInterface, \/\/ interfaceNumber\n    0, \/\/ bAlternateSetting\n    2, \/\/ bNumEndPoints\n    USB_DEVICE_CLASS_VENDOR_SPECIFIC, \/\/ bInterfaceClass = VENDOR SPECIFIC\n    0x00, \/\/ bSubClass\n    0x00, \/\/ Protocol\n    0, \/\/ interface\n\n    \/\/ENDPOINT OUT\n    7, \/\/ bLength\n    5, \/\/ bDescriptorType = ENDPOINT\n    USB_ENDPOINT_OUT(pluggedEndpoint), \/\/ EP1 OUT\n    USB_ENDPOINT_TYPE_BULK, \/\/ Bulk\n    0x00, 0x02, \/\/ 512 bytes\n    0,\n\n    \/\/ENDPOINT IN\n    7, \/\/ bLength\n    5, \/\/ bDescriptorType = ENDPOINT\n    USB_ENDPOINT_IN(pluggedEndpoint), \/\/ EP1 IN\n    USB_ENDPOINT_TYPE_BULK, \/\/ Bulk\n    0x00, 0x02, \/\/ 512 bytes\n    0\n  };\n\n  USBD_SendControl(0,desc,sizeof(desc));\n  return sizeof(desc);\n\n}\n\n\nint DataBulk_::getInterface(uint8_t* interfaceCount)\n{\n  \n  *interfaceCount += 1; \/\/ uses 1\n\tMSCDescriptor desc = {\n    D_INTERFACE(pluggedInterface, 2, USB_DEVICE_CLASS_VENDOR_SPECIFIC, 0x00, 0x00),\n\t\tD_ENDPOINT(USB_ENDPOINT_OUT(pluggedEndpoint), USB_ENDPOINT_TYPE_BULK, 512, 0x01),\n    D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_BULK, 512, 0x01) \n\t};\n\treturn USBD_SendControl(0, &amp;desc, sizeof(desc));\n\n}\n\n\nuint32_t DataBulk_::write(void * buf, size_t len)\n{\n  return USBD_Send(USB_ENDPOINT_IN(pluggedEndpoint),buf,len);\n  \/\/return UDD_Send(USB_ENDPOINT_IN(pluggedEndpoint) &amp; 0xF ,buf, (uint32_t) len);\n\n}\n\nuint8_t DataBulk_::getShortName(char * name)\n{\n  name&#91;0&#93; = 'V';\n  name&#91;1&#93; = 'N';\n  name&#91;2&#93; = 'D';\n  return 3;\n}\n\n  DataBulk_::DataBulk_(void) : PluggableUSBModule(2, 2, epType)\n{\n\tepType&#91;0&#93; = EP_TYPE_BULK_OUT_DATA;\t\/\/ BULK_ENDPOINT_OUT\n\tepType&#91;1&#93; = EP_TYPE_BULK_IN_DATA;\t\/\/ BULK_ENDPOINT_IN\n\t\n\tPluggableUSB().plug(this);\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">class<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">DataBulk_<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">public<\/span><span style=\"color: #D8DEE9FF\"> PluggableUSBModule <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">public<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DataBulk_<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">    \/\/uint32_t available();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">uint32_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">write<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">buf<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">size_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">len<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">protected<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">virtual<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">setup<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">USBSetup <\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">override;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">virtual<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">getInterface<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">interfaceCount<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">override;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">virtual<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">getDescriptor<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">USBSetup <\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">override;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">virtual<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">getShortName<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">char<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">override;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\">  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">uint32_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">epType<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">bool<\/span><span style=\"color: #D8DEE9FF\"> DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">setup<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">USBSetup<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedInterface <\/span><span style=\"color: #81A1C1\">!=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">wIndex<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">false;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> request <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bRequest<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> requestType <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bmRequestType<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">requestType <\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\"> REQUEST_RECIPIENT<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">request <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> GET_INTERFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\t\t\t\/\/ TODO: HID_GetReport();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> alternate_setting <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #88C0D0\">USBD_SendControl<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">alternate_setting<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">sizeof<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">alternate_setting<\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t\t<\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">request <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> SET_INTERFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\t\t\t\/\/ TODO: Send8(protocol);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t\t<\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">false;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">getDescriptor<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">USBSetup<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\t\/\/ Check if this is a Class Descriptor request<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bmRequestType<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!=<\/span><span style=\"color: #D8DEE9FF\"> REQUEST_DEVICETOHOST_STANDARD_INTERFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">setup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bRequest<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!=<\/span><span style=\"color: #D8DEE9FF\"> GET_DESCRIPTOR<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> desc[] <\/span><span style=\"color: #81A1C1\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">    \/\/interface descriptor<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">9<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bLength<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">4<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bDescriptorType = INTERFACE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    pluggedInterface<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ interfaceNumber<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bAlternateSetting<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bNumEndPoints<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    USB_DEVICE_CLASS_VENDOR_SPECIFIC<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bInterfaceClass = VENDOR SPECIFIC<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bSubClass<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ Protocol<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ interface<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">    \/\/ENDPOINT OUT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bLength<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">5<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bDescriptorType = ENDPOINT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">USB_ENDPOINT_OUT<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedEndpoint<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #616E88\"> \/\/ EP1 OUT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    USB_ENDPOINT_TYPE_BULK<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ Bulk<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">02<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ 512 bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">    \/\/ENDPOINT IN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bLength<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">5<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ bDescriptorType = ENDPOINT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">USB_ENDPOINT_IN<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedEndpoint<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #616E88\"> \/\/ EP1 IN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    USB_ENDPOINT_TYPE_BULK<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ Bulk<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">02<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #616E88\"> \/\/ 512 bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #88C0D0\">USBD_SendControl<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">desc<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">sizeof<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">desc<\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">sizeof<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">desc<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">getInterface<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">uint8_t*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">interfaceCount<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">interfaceCount <\/span><span style=\"color: #81A1C1\">+=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #616E88\"> \/\/ uses 1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\tMSCDescriptor desc <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">D_INTERFACE<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedInterface<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> USB_DEVICE_CLASS_VENDOR_SPECIFIC<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">00<\/span><span style=\"color: #ECEFF4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t\t<\/span><span style=\"color: #88C0D0\">D_ENDPOINT<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">USB_ENDPOINT_OUT<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedEndpoint<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\"> USB_ENDPOINT_TYPE_BULK<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">512<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">01<\/span><span style=\"color: #ECEFF4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">D_ENDPOINT<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">USB_ENDPOINT_IN<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedEndpoint<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\"> USB_ENDPOINT_TYPE_BULK<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">512<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">0x<\/span><span style=\"color: #B48EAD\">01<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">USBD_SendControl<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">desc<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">sizeof<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">desc<\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">uint32_t<\/span><span style=\"color: #D8DEE9FF\"> DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">write<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">buf<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">size_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">len<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">USBD_Send<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">USB_ENDPOINT_IN<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">pluggedEndpoint<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\">buf<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">len<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">  \/\/return UDD_Send(USB_ENDPOINT_IN(pluggedEndpoint) &amp; 0xF ,buf, (uint32_t) len);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">getShortName<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">char<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">V<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">N<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">D<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  DataBulk_<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #88C0D0\">DataBulk_<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #88C0D0\">PluggableUSBModule<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> epType<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #D8DEE9\">epType<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> EP_TYPE_BULK_OUT_DATA<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #616E88\">\t\/\/ BULK_ENDPOINT_OUT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #D8DEE9\">epType<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> EP_TYPE_BULK_IN_DATA<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #616E88\">\t\/\/ BULK_ENDPOINT_IN<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\t<\/span><span style=\"color: #88C0D0\">PluggableUSB<\/span><span style=\"color: #ECEFF4\">().<\/span><span style=\"color: #88C0D0\">plug<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">this<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Once our class properly inherits the Pluggable USB module base class, we can create the object<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>DataBulk_ USBData;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">DataBulk_ USBData<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>And use it to send data to the computer :<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>USBData.write(( void*) Data2,sizeof(Data2)); \/\/ uses our bulk endpoint, processed on the host by\n\/\/ libusb 1.0\n\/\/ sizeof(Data2) is 96 bytes.\n\nSerialUSB.println(\"USB data sent\") \/\/ uses the native USB port Serial over USB, processed on the host by the ttyACM driver<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">USBData<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">write<\/span><span style=\"color: #ECEFF4\">((<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">void*<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> Data2<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">sizeof<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">Data2<\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #616E88\"> \/\/ uses our bulk endpoint, processed on the host by<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ libusb 1.0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ sizeof(Data2) is 96 bytes.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">SerialUSB<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">println<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB data sent<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #616E88\"> \/\/ uses the native USB port Serial over USB, processed on the host by the ttyACM driver<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Testing enumeration on the host<\/h2>\n\n\n\n<p>To check for proper enumeration once the above code has been added to your sketch, compiled, and uploaded to the MCU is straightforward.<\/p>\n\n\n\n<p>As root, run :<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>cat \/sys\/kernel\/debug\/usb\/devices<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">cat<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">\/sys\/kernel\/debug\/usb\/devices<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>And the bottom relevant lines (ep 04 and 84 of interface 2) should appear once the native USB port is plugged to the computer :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"781\" height=\"327\" src=\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\" alt=\"\" class=\"wp-image-1643\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Libusb code<\/h2>\n\n\n\n<p>Now it is time to add libusb code to your C++ project, and add some #define and declarations<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ BULK USB VENDOR MODE\n#include &lt;libusb.h>\n\n\/\/defines for bulk interface\n#define URB_SIZE 96 \/\/ In our case URB_SIZE = Packet size = 96 bytes\n#define N_URBS 32 \/\/ 16 to 32 URBS in flight seems ok for data rates in the low MB\/s range\n#define VID 0x2341 \/\/ vendor ID of our device\n#define PID 0x003e \/\/ product ID of our device\n#define USB_BULK_IFACE 0x2 \/\/ Bulk interface ID\n#define EP_IN 0x84 \/\/ endpoint IN address\n#define EP_OUT 0x4 \/\/ endpoint OUT address (not used)\n\nstruct  libusb_transfer *usbxfer&#91;N_URBS&#93;;\nuint8_t  *usbbuf&#91;N_URBS&#93;;\nstd::atomic_bool readbulk_exit(false);\nstd::atomic_bool USB_transfer_active(true);\nlibusb_context *ctx;\nlibusb_device_handle *h;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ BULK USB VENDOR MODE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">include<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #ECEFF4\">&lt;<\/span><span style=\"color: #A3BE8C\">libusb.h<\/span><span style=\"color: #ECEFF4\">&gt;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/defines for bulk interface<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">URB_SIZE<\/span><span style=\"color: #5E81AC\"> 96 \/\/ In our case URB_SIZE = Packet size = 96 bytes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">N_URBS<\/span><span style=\"color: #5E81AC\"> 32 \/\/ 16 to 32 URBS in flight seems ok for data rates in the low MB\/s range<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">VID<\/span><span style=\"color: #5E81AC\"> 0x2341 \/\/ vendor ID of our device<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">PID<\/span><span style=\"color: #5E81AC\"> 0x003e \/\/ product ID of our device<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">USB_BULK_IFACE<\/span><span style=\"color: #5E81AC\"> 0x2 \/\/ Bulk interface ID<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">EP_IN<\/span><span style=\"color: #5E81AC\"> 0x84 \/\/ endpoint IN address<\/span><\/span>\n<span class=\"line\"><span style=\"color: #5E81AC; font-weight: bold\">#<\/span><span style=\"color: #81A1C1\">define<\/span><span style=\"color: #5E81AC\"> <\/span><span style=\"color: #88C0D0\">EP_OUT<\/span><span style=\"color: #5E81AC\"> 0x4 \/\/ endpoint OUT address (not used)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">struct<\/span><span style=\"color: #D8DEE9FF\">  libusb_transfer <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">usbxfer<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">N_URBS<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">usbbuf<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">N_URBS<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">std<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #D8DEE9FF\">atomic_bool <\/span><span style=\"color: #88C0D0\">readbulk_exit<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">false<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">std<\/span><span style=\"color: #ECEFF4\">::<\/span><span style=\"color: #D8DEE9FF\">atomic_bool <\/span><span style=\"color: #88C0D0\">USB_transfer_active<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">true<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">libusb_context <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">libusb_device_handle <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Add a FIFO scheduled thread (<strong>bulk_read_thread<\/strong>) that will make the initial transfer submit as well as pump the event driven libusb.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>pthread_t bulk_read_thread;\npthread_attr_t bulk_read_thread_attr;\n\npthread_attr_init(&amp;bulk_read_thread_attr);\n\npthread_attr_setinheritsched(&amp;bulk_read_thread_attr,PTHREAD_EXPLICIT_SCHED);\npthread_attr_setschedpolicy(&amp;bulk_read_thread_attr,SCHED_FIFO);\n\nsched_param param{};\n\nparam.sched_priority = 10;\n\npthread_attr_setschedparam(&amp;bulk_read_thread_attr,&amp;param);\n\nthread_rc = pthread_create(&amp;bulk_read_thread,&amp;bulk_read_thread_attr, BulkReadThread,NULL);\n\n\nif(thread_rc != 0)\n{\n\n    perror(\"Bulk reader thread creation error\");\n    DebugPrint(dbgstr(\"thread_rc\"),thread_rc,0);            \n    return -1;\n\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #8FBCBB\">pthread_t<\/span><span style=\"color: #D8DEE9FF\"> bulk_read_thread<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">pthread_attr_t<\/span><span style=\"color: #D8DEE9FF\"> bulk_read_thread_attr<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">pthread_attr_init<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread_attr<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">pthread_attr_setinheritsched<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread_attr<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">PTHREAD_EXPLICIT_SCHED<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">pthread_attr_setschedpolicy<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread_attr<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">SCHED_FIFO<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">sched_param param<\/span><span style=\"color: #ECEFF4\">{}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">param<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">sched_priority<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">pthread_attr_setschedparam<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread_attr<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">param<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">thread_rc <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">pthread_create<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread_attr<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> BulkReadThread<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">NULL<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">thread_rc <\/span><span style=\"color: #81A1C1\">!=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">perror<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Bulk reader thread creation error<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">thread_rc<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\">thread_rc<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\">            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>the sched_priority attribute is very important. use the ps command to get SCHED_FIFO threads and their priorities, and set priority accordingly as to obtain a stable data flow and so as not make the system irresponsive or lag. Remember that SCHED_FIFO threads have precedence over most of other threads on a system (SCHED_OTHER)<\/p>\n\n\n\n<p>The Thread function follows :<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>void * BulkReadThread(void * arg)\n{\n    mlockall(MCL_CURRENT | MCL_FUTURE);\n\n    DebugPrint(dbgstr(\"Enter USB Bulk read thread\"),0);\n                \n    if(USE_BULK)\n    {\n        for(int i = 0; i &lt; N_URBS; i++)\n        {\n            libusb_submit_transfer(usbxfer&#91;i&#93;);\n        }\n    }\n\n\n    while(!(readbulk_exit.load()))\n    {\n        \/\/usleep(100);\n        libusb_handle_events(ctx);\n        \/\/DebugPrint(dbgstr(\"PutSerialSamples ok\"),0);  \n        sched_yield();\n    }\n\n    sched_yield();\n    return 0;\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BulkReadThread<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">arg<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">mlockall<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">MCL_CURRENT <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #D8DEE9FF\"> MCL_FUTURE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Enter USB Bulk read thread<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">USE_BULK<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> i <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> i <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> N_URBS<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #88C0D0\">libusb_submit_transfer<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">usbxfer<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">while<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">!<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">readbulk_exit<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">load<\/span><span style=\"color: #ECEFF4\">()))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">        \/\/usleep(100);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">libusb_handle_events<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">        \/\/DebugPrint(dbgstr(&quot;PutSerialSamples ok&quot;),0);  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">sched_yield<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">sched_yield<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The <strong>readbulk_exit <\/strong>atomic boolean is used to signal the thread (externally) that it needs to stop USB event polling operations which will quench transfers, Which is used in a graceful program termination.<\/p>\n\n\n\n<p>This thread does not populate directly the data buffer so it can be consumed. It only submits initial transfer requests and pumps events through <strong>libusb_handle_events(ctx)<\/strong> The setup of the population of the buffer is done by <strong>libusb_fill_bulk_transfer()<\/strong> once, where we supply a callback function, <strong>rx_usb_bulk()<\/strong>. See below.<\/p>\n\n\n\n<p><strong>sched_yield()<\/strong> in that case is quite important as it guarantees some throttling and helps with system responsiveness. It relinquishes the CPU and other <strong>sched_fifo<\/strong> threads can be immediately processed, regardless of priority.<\/p>\n\n\n\n<p><strong>mlockall() <\/strong>is an optimization as it locks all pages in memory and prevents paging. It may have profound effects on allocation, and should probably happen when most of allocation is done or memory reserved using techniques appropriate, which are beyond the scope of this article. Use with caution.<\/p>\n\n\n\n<p>Of course, now we also need to initialize the whole libusb stack to handle our device :<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\n\nlibusb_init(&amp;ctx);\nlibusb_set_option(ctx,LIBUSB_OPTION_LOG_LEVEL,LIBUSB_LOG_LEVEL_WARNING);\n\n\n\n\nh = libusb_open_device_with_vid_pid(ctx,VID,PID);\nif (!h)\n{\n    DebugPrint(dbgstr(\"USB open device failed, is it plugged ?\"),0);\n    fflush(stdout);\n    return 1;\n}\nDebugPrint(dbgstr(\"USB open device OK\"),0);\n    \n\nif(libusb_kernel_driver_active(h,USB_BULK_IFACE) == 1)\n{\n    libusb_detach_kernel_driver(h,USB_BULK_IFACE);\n    DebugPrint(dbgstr(\"kernel driver detach OK (should not happen, no driver should be attached).\"),0);\n}\n\nif(libusb_claim_interface(h,USB_BULK_IFACE) &lt; 0)\n{\n    DebugPrint(dbgstr(\"USB claim interface failed.\"),0);\n    fflush(stdout);\n    return 1;\n}\nDebugPrint(dbgstr(\"USB claim interface OK.\"),0);\n\n\nfor(uint8_t i = 0; i &lt; N_URBS; i++)\n{\n    usbbuf&#91;i&#93; = (uint8_t *) aligned_alloc(64,URB_SIZE);\n    usbxfer&#91;i&#93; = libusb_alloc_transfer(0);\n    libusb_fill_bulk_transfer(\n        usbxfer&#91;i&#93;,\n        h,\n        EP_IN,\n        usbbuf&#91;i&#93;,\n        URB_SIZE,\n        rx_usb_bulk,\n        NULL,\n        0\n    );\n}\n\nreadbulk_exit.store(true);\n        \n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">libusb_init<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">libusb_set_option<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">LIBUSB_OPTION_LOG_LEVEL<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">LIBUSB_LOG_LEVEL_WARNING<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">h <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">libusb_open_device_with_vid_pid<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">VID<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">PID<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">!<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB open device failed, is it plugged ?<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">fflush<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">stdout<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB open device OK<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">libusb_kernel_driver_active<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">USB_BULK_IFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">libusb_detach_kernel_driver<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">USB_BULK_IFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">kernel driver detach OK (should not happen, no driver should be attached).<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">libusb_claim_interface<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">USB_BULK_IFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB claim interface failed.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">fflush<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">stdout<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB claim interface OK.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> i <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> i <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> N_URBS<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">usbbuf<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">uint8_t<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">aligned_alloc<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">64<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">URB_SIZE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">usbxfer<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">libusb_alloc_transfer<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">libusb_fill_bulk_transfer<\/span><span style=\"color: #ECEFF4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">usbxfer<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        h<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        EP_IN<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">usbbuf<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        URB_SIZE<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        rx_usb_bulk<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">NULL<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">readbulk_exit<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">store<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">true<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>And finally, the rx_usb_bulk() callback function :<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>static void rx_usb_bulk(struct libusb_transfer *t)\n{\n    if(t->status == LIBUSB_TRANSFER_COMPLETED)\n    {\n        if(t->actual_length > 0)\n        {\n            PutSamplesUSB(t->buffer,t->actual_length);\n            \/\/DebugPrint(dbgstr(\"Processing of USB transfer buffer,t->actual_length\"),t->actual_length,0);\n    \n        }\n        if (USB_transfer_active.load())\n        {\n            libusb_submit_transfer(t);\n            \/\/reschedule transfer immediately, unless signalled to stop.\n        }\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">static<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">rx_usb_bulk<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">struct<\/span><span style=\"color: #D8DEE9FF\"> libusb_transfer <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9\">t<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">t<\/span><span style=\"color: #ECEFF4\">-&gt;<\/span><span style=\"color: #D8DEE9\">status<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> LIBUSB_TRANSFER_COMPLETED<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">t<\/span><span style=\"color: #ECEFF4\">-&gt;<\/span><span style=\"color: #D8DEE9\">actual_length<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #88C0D0\">PutSamplesUSB<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">t<\/span><span style=\"color: #ECEFF4\">-&gt;<\/span><span style=\"color: #D8DEE9\">buffer<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9\">t<\/span><span style=\"color: #ECEFF4\">-&gt;<\/span><span style=\"color: #D8DEE9\">actual_length<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">            \/\/DebugPrint(dbgstr(&quot;Processing of USB transfer buffer,t-&gt;actual_length&quot;),t-&gt;actual_length,0);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">USB_transfer_active<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">load<\/span><span style=\"color: #ECEFF4\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #88C0D0\">libusb_submit_transfer<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">t<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">            \/\/reschedule transfer immediately, unless signalled to stop.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><strong>PutSamplesUSB()<\/strong> is a user project function that handles incoming buffer data, to populate, let&#8217;s say a circular buffer from the t-&gt;buffer source.<\/p>\n\n\n\n<p><strong>USB_transfer_active<\/strong> is an atomic boolean variable that signals to stop submitting new transfers. It needs to be set to false first before setting readbulk_exit to true (that in turns make the the thread that processes libusb events to join). This happens usually in the graceful process exit \/ cleanup routines. See below.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cleanup<\/h2>\n\n\n\n<p>Cleanup is required in traditional C++ fashion as well as libusb required calls. But first the dedicated thread that does the libusb event polling must be notified to join.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>USB_transfer_active.store(false);\nDebugPrint(dbgstr(\"setting USB_transfer_active to false (won't submit new transfers)\"),0);\n\nfor(int i=0; i &lt; N_URBS;i++)\n{\n    libusb_cancel_transfer(usbxfer&#91;i&#93;);\n    DebugPrint(dbgstr(\"cancelling pending transfers, index=\"),i,0);\n\n}\nusleep(10000);\nlibusb_release_interface(h,USB_BULK_IFACE);\nDebugPrint(dbgstr(\"interface released\"),0);\n\nlibusb_close(h);\nDebugPrint(dbgstr(\"USB device handle closed\"),0);\n\n\nreadbulk_exit.store(true);\n\nint s = pthread_join(bulk_read_thread,nullptr); \/\/ waiting for USB bulk read thread to join\nif(s == 0)\n{\n    DebugPrint(dbgstr(\"USB bulk read thread joined\"),s,0);\n    libusb_exit(ctx);\n    DebugPrint(dbgstr(\"libusb exit\"),0);\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">USB_transfer_active<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">store<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">false<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">setting USB_transfer_active to false (won&#39;t submit new transfers)<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> i<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> i <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> N_URBS<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">libusb_cancel_transfer<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">usbxfer<\/span><span style=\"color: #ECEFF4\">&#91;<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">&#93;)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">cancelling pending transfers, index=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\">i<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">usleep<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #B48EAD\">10000<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">libusb_release_interface<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\">USB_BULK_IFACE<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">interface released<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">libusb_close<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">h<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB device handle closed<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">readbulk_exit<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">store<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">true<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">int<\/span><span style=\"color: #D8DEE9FF\"> s <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">pthread_join<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">bulk_read_thread<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #81A1C1\">nullptr<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #616E88\"> \/\/ waiting for USB bulk read thread to join<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">s <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">USB bulk read thread joined<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #D8DEE9FF\">s<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">libusb_exit<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">ctx<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">DebugPrint<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">dbgstr<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">libusb exit<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">),<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Here we use the boolean state variables to communicate with the thread to halt USB communication before releasing libusb resources.<\/p>\n\n\n\n<p>This concludes the article about adding USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A substantial advantage of the Arduino Due MCU is the native USB High Speed interface allowing up to 480 Mbps transfers. Another option are the costlier Teensy boards that are really mature and provide a solid framework for USB bulk endpoints data interfaces not limited to ttyACM Serial over USB interfaces. However, it is absolutely<\/p><\/div>\n<div class=\"blog-btn\"><a href=\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\" class=\"home-blog-btn\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","pmpro_default_level":"","footnotes":""},"categories":[15,16],"tags":[],"class_list":["post-1625","post","type-post","status-publish","format-standard","hentry","category-diy-projects","category-information-technology","pmpro-has-access"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.<\/title>\n<meta name=\"description\" content=\"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.\" \/>\n<meta property=\"og:description\" content=\"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\" \/>\n<meta property=\"og:site_name\" content=\"SKYNEXT Tech.\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-13T04:05:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-02-13T14:49:11+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\" \/>\n\t<meta property=\"og:image:width\" content=\"781\" \/>\n\t<meta property=\"og:image:height\" content=\"327\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"R.Verissimo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"R.Verissimo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\"},\"author\":{\"name\":\"R.Verissimo\",\"@id\":\"https:\/\/www.skynext.tech\/#\/schema\/person\/6b71040d3e4353a85583550901159cd8\"},\"headline\":\"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux.\",\"datePublished\":\"2026-02-13T04:05:15+00:00\",\"dateModified\":\"2026-02-13T14:49:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\"},\"wordCount\":1284,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.skynext.tech\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\",\"articleSection\":[\"DIY Projects\",\"Information Technology\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\",\"url\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\",\"name\":\"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.\",\"isPartOf\":{\"@id\":\"https:\/\/www.skynext.tech\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\",\"datePublished\":\"2026-02-13T04:05:15+00:00\",\"dateModified\":\"2026-02-13T14:49:11+00:00\",\"description\":\"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage\",\"url\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\",\"contentUrl\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png\",\"width\":781,\"height\":327},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.skynext.tech\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux.\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.skynext.tech\/#website\",\"url\":\"https:\/\/www.skynext.tech\/\",\"name\":\"SKYNEXT Tech.\",\"description\":\"Power Electronics &amp; Reverse Engineering\",\"publisher\":{\"@id\":\"https:\/\/www.skynext.tech\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.skynext.tech\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.skynext.tech\/#organization\",\"name\":\"SKYNEXT Tech.\",\"alternateName\":\"DELIVERYSIMO EIRL\",\"url\":\"https:\/\/www.skynext.tech\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.skynext.tech\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2019\/09\/cropped-SKYNEXT_logo_square-2.png\",\"contentUrl\":\"https:\/\/www.skynext.tech\/wp-content\/uploads\/2019\/09\/cropped-SKYNEXT_logo_square-2.png\",\"width\":210,\"height\":210,\"caption\":\"SKYNEXT Tech.\"},\"image\":{\"@id\":\"https:\/\/www.skynext.tech\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.skynext.tech\/#\/schema\/person\/6b71040d3e4353a85583550901159cd8\",\"name\":\"R.Verissimo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.skynext.tech\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0bf345444b71baae1301e50a1a8cbeb98a5b7f41b85ffe9e1e6c2640ef23b528?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0bf345444b71baae1301e50a1a8cbeb98a5b7f41b85ffe9e1e6c2640ef23b528?s=96&d=mm&r=g\",\"caption\":\"R.Verissimo\"},\"url\":\"https:\/\/www.skynext.tech\/index.php\/author\/wpadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.","description":"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/","og_locale":"en_US","og_type":"article","og_title":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.","og_description":"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.","og_url":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/","og_site_name":"SKYNEXT Tech.","article_published_time":"2026-02-13T04:05:15+00:00","article_modified_time":"2026-02-13T14:49:11+00:00","og_image":[{"width":781,"height":327,"url":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png","type":"image\/png"}],"author":"R.Verissimo","twitter_card":"summary_large_image","twitter_misc":{"Written by":"R.Verissimo","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#article","isPartOf":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/"},"author":{"name":"R.Verissimo","@id":"https:\/\/www.skynext.tech\/#\/schema\/person\/6b71040d3e4353a85583550901159cd8"},"headline":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux.","datePublished":"2026-02-13T04:05:15+00:00","dateModified":"2026-02-13T14:49:11+00:00","mainEntityOfPage":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/"},"wordCount":1284,"commentCount":0,"publisher":{"@id":"https:\/\/www.skynext.tech\/#organization"},"image":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage"},"thumbnailUrl":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png","articleSection":["DIY Projects","Information Technology"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/","url":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/","name":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux. - SKYNEXT Tech.","isPartOf":{"@id":"https:\/\/www.skynext.tech\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage"},"image":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage"},"thumbnailUrl":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png","datePublished":"2026-02-13T04:05:15+00:00","dateModified":"2026-02-13T14:49:11+00:00","description":"How to improve data transfer rates using the native USB by leveraging the power of USB 2.0 high speed on Arduino Due and libusb on Linux. With C++ example.","breadcrumb":{"@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#primaryimage","url":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png","contentUrl":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2026\/02\/usb_endpoints.png","width":781,"height":327},{"@type":"BreadcrumbList","@id":"https:\/\/www.skynext.tech\/index.php\/2026\/02\/13\/usb-2-0-high-speed-bulk-endpoints-on-arduino-due-mcu-and-libusb-interfacing-on-linux\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.skynext.tech\/"},{"@type":"ListItem","position":2,"name":"USB 2.0 (High-Speed) bulk endpoints on Arduino Due MCU and libusb interfacing on Linux."}]},{"@type":"WebSite","@id":"https:\/\/www.skynext.tech\/#website","url":"https:\/\/www.skynext.tech\/","name":"SKYNEXT Tech.","description":"Power Electronics &amp; Reverse Engineering","publisher":{"@id":"https:\/\/www.skynext.tech\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.skynext.tech\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.skynext.tech\/#organization","name":"SKYNEXT Tech.","alternateName":"DELIVERYSIMO EIRL","url":"https:\/\/www.skynext.tech\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.skynext.tech\/#\/schema\/logo\/image\/","url":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2019\/09\/cropped-SKYNEXT_logo_square-2.png","contentUrl":"https:\/\/www.skynext.tech\/wp-content\/uploads\/2019\/09\/cropped-SKYNEXT_logo_square-2.png","width":210,"height":210,"caption":"SKYNEXT Tech."},"image":{"@id":"https:\/\/www.skynext.tech\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.skynext.tech\/#\/schema\/person\/6b71040d3e4353a85583550901159cd8","name":"R.Verissimo","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.skynext.tech\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/0bf345444b71baae1301e50a1a8cbeb98a5b7f41b85ffe9e1e6c2640ef23b528?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0bf345444b71baae1301e50a1a8cbeb98a5b7f41b85ffe9e1e6c2640ef23b528?s=96&d=mm&r=g","caption":"R.Verissimo"},"url":"https:\/\/www.skynext.tech\/index.php\/author\/wpadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/posts\/1625","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/comments?post=1625"}],"version-history":[{"count":30,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/posts\/1625\/revisions"}],"predecessor-version":[{"id":1658,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/posts\/1625\/revisions\/1658"}],"wp:attachment":[{"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/media?parent=1625"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/categories?post=1625"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skynext.tech\/index.php\/wp-json\/wp\/v2\/tags?post=1625"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}