Skip to content

feat: update usb bulk trans and add linux test driver#23

Merged
YanKE01 merged 1 commit intomasterfrom
feat/add_driver_for_bulk_trans
Jun 25, 2025
Merged

feat: update usb bulk trans and add linux test driver#23
YanKE01 merged 1 commit intomasterfrom
feat/add_driver_for_bulk_trans

Conversation

@YanKE01
Copy link
Owner

@YanKE01 YanKE01 commented Jun 25, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a Linux kernel USB driver for bulk transfer testing with packet framing and CRC validation.
    • Enhanced the ESP32-S3 USB bulk transfer example to support framed data reception, header parsing, and CRC integrity checks.
  • Documentation
    • Expanded the README with details about the Linux host driver, transfer protocol, and updated compilation/testing instructions.
  • Chores
    • Added a .gitignore file to exclude build artifacts in the Linux driver directory.
  • Refactor
    • Replaced the simple echo protocol with a stateful, framed packet reception and error checking mechanism.
  • Revert
    • Removed the Python-based USB bulk transfer test script.

@coderabbitai
Copy link

coderabbitai bot commented Jun 25, 2025

Walkthrough

This update introduces a Linux kernel USB driver for bulk transfer testing, enhances the ESP32-S3 device-side example to support framed packet reception with CRC validation, and expands documentation. The previous Python test script is removed, replaced by the new Linux driver. Build instructions and .gitignore for the Linux driver are added.

Changes

File(s) Change Summary
linux_driver/Makefile, linux_driver/.gitignore, linux_driver/usb.c Added new Linux kernel USB driver with build files and ignore rules for artifacts.
main/bulk_trans.c, main/tusb/tusb_config.h Enhanced device code for framed data reception, CRC validation, new suspend/resume callbacks, and buffer size increases.
README.md Expanded documentation to cover Linux driver usage, protocol details, and build/testing steps.
test.py Removed the old Python USB test script.

Sequence Diagram(s)

sequenceDiagram
    participant LinuxHost as Linux Host Driver
    participant USB as USB Bus
    participant ESP32 as ESP32-S3 Device

    LinuxHost->>USB: Bulk OUT transfer (packet with header + payload)
    USB->>ESP32: Delivers USB packet(s)
    ESP32->>ESP32: Buffers data, parses header, checks CRC
    ESP32-->>ESP32: (Optional) Logs payload if CRC matches
Loading

Possibly related PRs

  • YanKE01/esp_demos#19: Introduced the initial USB bulk transfer example project with basic echo functionality and supporting build files, which this PR extends with new protocol and host driver.

Poem

A bunny with bytes in its hat,
Hopped in with a kernel-format.
Now Linux and ESP converse in style,
With CRC checks and a buffer pile.
The Python test hops away,
As new drivers come out to play!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
examples/usb/device/bulk_trans/linux_driver/Makefile (1)

11-20: Add phony target declarations for better Makefile practices.

Declare non-file targets as phony to prevent conflicts with files of the same name.

+.PHONY: modules modules_install install clean
+
 modules:
 	$(MAKE) -C $(KERNEL_SOURCE_DIR) M=$(PWD) modules
examples/usb/device/bulk_trans/linux_driver/usb.c (2)

24-38: Consider using kernel's built-in CRC16 function.

You include <linux/crc16.h> but implement your own CRC function. The kernel provides crc16() with various polynomials.

-static uint16_t crc16_ccitt(const uint8_t *data, uint16_t len, uint16_t init)
-{
-    uint16_t crc = init;
-    while (len--) {
-        crc ^= (*data++) << 8;
-        for (int i = 0; i < 8; i++) {
-            if (crc & 0x8000) {
-                crc = (crc << 1) ^ 0x1021;
-            } else {
-                crc <<= 1;
-            }
-        }
-    }
-    return crc;
-}

Then replace the call at line 81:

-    hdr->crc16 = cpu_to_le16(crc16_ccitt(tx_buf + sizeof(*hdr), total_len, 0x0000));
+    hdr->crc16 = cpu_to_le16(crc_ccitt(0x0000, tx_buf + sizeof(*hdr), total_len));

Note: The kernel's crc_ccitt() function uses the same polynomial (0x1021) and provides the same result.


40-94: Unusual driver pattern - consider the implications.

This driver performs a one-shot USB transfer during probe and always returns 0 (success). This means:

  • The transfer happens immediately when the device is connected
  • No cleanup or further interaction is possible
  • The driver remains bound but inactive after the initial transfer

This pattern is acceptable for a test driver but differs from typical USB drivers that set up for ongoing communication.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b69cb7 and 80528aa.

📒 Files selected for processing (6)
  • examples/usb/device/bulk_trans/README.md (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/.gitignore (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/Makefile (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/usb.c (1 hunks)
  • examples/usb/device/bulk_trans/main/bulk_trans.c (1 hunks)
  • examples/usb/device/bulk_trans/test.py (0 hunks)
💤 Files with no reviewable changes (1)
  • examples/usb/device/bulk_trans/test.py
🧰 Additional context used
🪛 checkmake (0.2.2)
examples/usb/device/bulk_trans/linux_driver/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)


[warning] 17-17: Target "install" should be declared PHONY.

(phonydeclared)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (4)
examples/usb/device/bulk_trans/linux_driver/.gitignore (1)

1-7: LGTM!

The .gitignore file correctly excludes all common Linux kernel module build artifacts.

examples/usb/device/bulk_trans/README.md (1)

3-7: Clear documentation of the Linux driver integration.

The README effectively explains the packet size mismatch and encoding requirements, providing clear compilation and testing instructions.

examples/usb/device/bulk_trans/main/bulk_trans.c (2)

44-58: CRC16-CCITT implementation is correct.

The CRC calculation correctly implements CRC16-CCITT with polynomial 0x1021, matching the Linux driver implementation.


60-133: Well-structured framed packet reception logic.

The implementation correctly handles:

  • Header parsing with length and CRC fields
  • Multi-packet buffering for frames larger than endpoint size
  • CRC validation after complete frame reception
  • Proper state management and error handling

obj-m := $(DRIVER_NAME).o

DRIVER_FILES := usb.o
CFLAGS_main.o = -O0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect CFLAGS variable name.

The CFLAGS variable references main.o but your source file compiles to usb.o. This flag setting will have no effect.

-CFLAGS_main.o = -O0
+CFLAGS_usb.o = -O0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CFLAGS_main.o = -O0
-CFLAGS_main.o = -O0
+CFLAGS_usb.o = -O0
🤖 Prompt for AI Agents
In examples/usb/device/bulk_trans/linux_driver/Makefile at line 7, the CFLAGS
variable is incorrectly named CFLAGS_main.o, but the source file being compiled
is usb.o. Rename the variable to CFLAGS_usb.o to ensure the compiler flags apply
correctly to the usb.o compilation.

printf("\n");
}

// Reset statet
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in comment.

-            // Reset statet
+            // Reset state
🤖 Prompt for AI Agents
In examples/usb/device/bulk_trans/main/bulk_trans.c at line 126, there is a typo
in the comment "Reset statet". Correct the comment to "Reset state" to fix the
spelling mistake.


int in_pipe = 0, out_pipe = 0;

// find input and oupt endpoint
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in comment.

-    // find input and oupt endpoint
+    // find input and output endpoint
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// find input and oupt endpoint
// find input and output endpoint
🤖 Prompt for AI Agents
In examples/usb/device/bulk_trans/linux_driver/usb.c at line 49, there is a typo
in the comment "find input and oupt endpoint". Correct the typo by changing
"oupt" to "output" to improve clarity and professionalism in the code comments.

Comment on lines +6 to +9
#define BULK_PACKET_MAX_SIZE 64
#define PROTOCOL_HEADER_SIZE 6
#define PAYLOAD_SIZE (BULK_PACKET_MAX_SIZE - PROTOCOL_HEADER_SIZE)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unused macro definitions.

The macros BULK_PACKET_MAX_SIZE, PROTOCOL_HEADER_SIZE, and PAYLOAD_SIZE are defined but never used in the code. The actual header size is correctly calculated using sizeof(struct usb_packet_header).

-#define BULK_PACKET_MAX_SIZE 64
-#define PROTOCOL_HEADER_SIZE 6
-#define PAYLOAD_SIZE (BULK_PACKET_MAX_SIZE - PROTOCOL_HEADER_SIZE)
-
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#define BULK_PACKET_MAX_SIZE 64
#define PROTOCOL_HEADER_SIZE 6
#define PAYLOAD_SIZE (BULK_PACKET_MAX_SIZE - PROTOCOL_HEADER_SIZE)
🤖 Prompt for AI Agents
In examples/usb/device/bulk_trans/linux_driver/usb.c around lines 6 to 8, the
macros BULK_PACKET_MAX_SIZE, PROTOCOL_HEADER_SIZE, and PAYLOAD_SIZE are defined
but not used anywhere in the code. Remove these unused macro definitions to
clean up the code since the header size is already correctly calculated using
sizeof(struct usb_packet_header).

@YanKE01 YanKE01 force-pushed the feat/add_driver_for_bulk_trans branch from 80528aa to 096fdbc Compare June 25, 2025 10:27
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
examples/usb/device/bulk_trans/linux_driver/Makefile (1)

7-7: Fix incorrect CFLAGS variable name.

The CFLAGS variable references main.o but your source file compiles to usb.o. This flag setting will have no effect.

-CFLAGS_main.o = -O0
+CFLAGS_usb.o = -O0
examples/usb/device/bulk_trans/main/bulk_trans.c (1)

155-155: Fix typo in comment.

-            // Reset statet
+            // Reset state
examples/usb/device/bulk_trans/linux_driver/usb.c (2)

7-9: Remove unused macro definitions.

The macros BULK_PACKET_MAX_SIZE, PROTOCOL_HEADER_SIZE, and PAYLOAD_SIZE are defined but never used in the code. The actual header size is correctly calculated using sizeof(struct usb_packet_header).

-#define BULK_PACKET_MAX_SIZE 64
-#define PROTOCOL_HEADER_SIZE 6
-#define PAYLOAD_SIZE (BULK_PACKET_MAX_SIZE - PROTOCOL_HEADER_SIZE)
-

51-51: Fix typo in comment.

-    // find input and oupt endpoint
+    // find input and output endpoint
🧹 Nitpick comments (2)
examples/usb/device/bulk_trans/linux_driver/Makefile (1)

11-21: Add missing phony target declarations.

The Makefile should declare phony targets to prevent conflicts with files of the same name and improve build reliability.

+.PHONY: all modules modules_install install clean
+
+all: modules
+
 modules:
 	$(MAKE) -C $(KERNEL_SOURCE_DIR) M=$(PWD) modules
 
 modules_install:
 	$(MAKE) -C $(KERNEL_SOURCE_DIR) M=$(PWD) modules_install
 
 install: modules_install
 
 clean:
 	$(MAKE) -C $(KERNEL_SOURCE_DIR) M=$(PWD) clean
examples/usb/device/bulk_trans/linux_driver/usb.c (1)

95-108: Improve error handling for receive buffer allocation.

The function returns after failing to allocate the receive buffer, but the transmit operation has already completed successfully. Consider this a partial success rather than complete failure.

 uint8_t *rx_buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
 if (!rx_buf) {
     pr_err("Failed to allocate receive buffer\n");
-    return -ENOMEM;
+    pr_warn("Skipping response verification due to memory allocation failure\n");
+    return 0; // Transmit was successful
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80528aa and 096fdbc.

📒 Files selected for processing (7)
  • examples/usb/device/bulk_trans/README.md (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/.gitignore (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/Makefile (1 hunks)
  • examples/usb/device/bulk_trans/linux_driver/usb.c (1 hunks)
  • examples/usb/device/bulk_trans/main/bulk_trans.c (1 hunks)
  • examples/usb/device/bulk_trans/main/tusb/tusb_config.h (1 hunks)
  • examples/usb/device/bulk_trans/test.py (0 hunks)
💤 Files with no reviewable changes (1)
  • examples/usb/device/bulk_trans/test.py
✅ Files skipped from review due to trivial changes (1)
  • examples/usb/device/bulk_trans/main/tusb/tusb_config.h
🚧 Files skipped from review as they are similar to previous changes (2)
  • examples/usb/device/bulk_trans/linux_driver/.gitignore
  • examples/usb/device/bulk_trans/README.md
🧰 Additional context used
🪛 checkmake (0.2.2)
examples/usb/device/bulk_trans/linux_driver/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)


[warning] 17-17: Target "install" should be declared PHONY.

(phonydeclared)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (7)
examples/usb/device/bulk_trans/main/bulk_trans.c (4)

14-24: LGTM! Well-structured packet header and state management.

The packed header structure and static state variables are properly defined for the framed packet protocol.


44-58: LGTM! Correct CRC16-CCITT implementation.

The CRC16-CCITT implementation matches the standard algorithm with polynomial 0x1021. This aligns with the Linux driver implementation for proper packet validation.


69-91: LGTM! Proper header parsing and validation.

The code correctly handles header extraction, validates payload size against buffer limits, and manages frame state initialization.


128-133: Verify memory allocation error handling.

The code allocates a response buffer but doesn't reset the frame state if allocation fails, which could leave the system in an inconsistent state.

Consider resetting the frame state on allocation failure:

 uint8_t *response_buf = malloc(sizeof(usb_packet_header_t) + response_len);
 if (!response_buf) {
     ESP_LOGE(TAG, "Failed to allocate response buffer");
+    // Reset frame state on allocation failure
+    frame_active = false;
+    received_total = 0;
+    expected_total = 0;
+    expected_crc16 = 0;
     return;
 }
examples/usb/device/bulk_trans/linux_driver/usb.c (3)

26-40: LGTM! CRC implementation matches device side.

The CRC16-CCITT implementation is identical to the device-side code, ensuring proper packet validation between host and device.


76-83: LGTM! Proper endianness handling.

The code correctly uses cpu_to_le16() and le16_to_cpu() for cross-platform compatibility, ensuring the USB packet format is consistent regardless of host architecture.


121-127: LGTM! Comprehensive CRC verification.

The CRC verification logic properly extracts the payload, calculates the checksum, and provides clear logging for both success and failure cases.

Comment on lines +147 to +152
int ret = 0;
ret = tud_vendor_n_write(0, response_buf, sizeof(usb_packet_header_t) + response_len);
if (ret < 0) {
ESP_LOGE(TAG, "USB bulk write failed: %d", ret);
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for partial USB writes.

The code checks for write failure but doesn't handle the case where tud_vendor_n_write returns a partial write (0 < ret < expected_size).

-int ret = 0;
-ret = tud_vendor_n_write(0, response_buf, sizeof(usb_packet_header_t) + response_len);
-if (ret < 0) {
-    ESP_LOGE(TAG, "USB bulk write failed: %d", ret);
-}
+int expected_size = sizeof(usb_packet_header_t) + response_len;
+int ret = tud_vendor_n_write(0, response_buf, expected_size);
+if (ret < 0) {
+    ESP_LOGE(TAG, "USB bulk write failed: %d", ret);
+} else if (ret != expected_size) {
+    ESP_LOGE(TAG, "Partial USB write: %d/%d bytes", ret, expected_size);
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int ret = 0;
ret = tud_vendor_n_write(0, response_buf, sizeof(usb_packet_header_t) + response_len);
if (ret < 0) {
ESP_LOGE(TAG, "USB bulk write failed: %d", ret);
}
int expected_size = sizeof(usb_packet_header_t) + response_len;
int ret = tud_vendor_n_write(0, response_buf, expected_size);
if (ret < 0) {
ESP_LOGE(TAG, "USB bulk write failed: %d", ret);
} else if (ret != expected_size) {
ESP_LOGE(TAG, "Partial USB write: %d/%d bytes", ret, expected_size);
}
🤖 Prompt for AI Agents
In examples/usb/device/bulk_trans/main/bulk_trans.c around lines 147 to 152, the
code checks for a negative return value from tud_vendor_n_write but does not
handle partial writes where the return value is positive but less than the
expected size. Update the code to detect if ret is greater than zero but less
than the total bytes intended to write, and implement appropriate error handling
or retry logic to ensure the full data is sent.

@YanKE01 YanKE01 merged commit c8f7d86 into master Jun 25, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant