diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index ba1f23d0..50c693af 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -12,7 +12,7 @@ on: env: - MAVEN_ARGS: -B -V -ntp -e -Djansi.passthrough=true -Dstyle.color=always + MVN_DEFAULT_ARGS: -B -V -ntp -e -Djansi.passthrough=true -Dstyle.color=always jobs: @@ -23,35 +23,48 @@ jobs: matrix: os: [ubuntu-latest, macOS-latest, windows-latest] runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v5 with: distribution: 'zulu' - java-version: '21' - cache: 'maven' - - name: Configure GPG key + java-version: '25' + - name: Configure unit test GPG key run: | - echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import + echo -n "$UNIT_TEST_SIGNING_KEY" | base64 --decode | gpg --import env: - GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} - shell: bash + UNIT_TEST_SIGNING_KEY: ${{ vars.UNIT_TEST_SIGNING_KEY }} - name: Build java-does-usb - run: ./mvnw $MAVEN_ARGS -DskipTests clean install javadoc:javadoc + run: ./mvnw $MVN_DEFAULT_ARGS -DskipTests clean install javadoc:javadoc + working-directory: ./java-does-usb + - name: Determine java-does-usb version + id: libver + run: echo "version=$(./mvnw -q -ntp help:evaluate -Dexpression=project.version -DforceStdout)" >> "$GITHUB_OUTPUT" working-directory: ./java-does-usb + # Examples pin the latest released version so they double as user-facing documentation; + # override that pin here to compile them against the HEAD version just installed above. - name: Example "bulk_transfer" - run: ./mvnw $MAVEN_ARGS clean compile + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean compile working-directory: ./examples/bulk_transfer - name: Example "enumerate" - run: ./mvnw $MAVEN_ARGS clean compile + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean compile working-directory: ./examples/enumerate + - name: Example "enumerate" (Kotlin) + run: ./gradlew -PjavaDoesUsbVersion=${{ steps.libver.outputs.version }} clean build + working-directory: ./examples/enumerate_kotlin - name: Example "monitor" - run: ./mvnw $MAVEN_ARGS clean compile + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean compile working-directory: ./examples/monitor + - name: Example "monitor" (Kotlin) + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean package + working-directory: ./examples/monitor_kotlin - name: Example "stm_dfu" - run: ./mvnw $MAVEN_ARGS clean compile + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean compile working-directory: ./examples/stm_dfu - name: Example "epaper_display" - run: ./mvnw $MAVEN_ARGS clean compile + run: ./mvnw $MVN_DEFAULT_ARGS -Djava-does-usb.version=${{ steps.libver.outputs.version }} clean compile working-directory: ./examples/epaper_display diff --git a/.github/workflows/test-devices.yaml b/.github/workflows/test-devices.yaml index 4ad663f7..0ad9cc6e 100644 --- a/.github/workflows/test-devices.yaml +++ b/.github/workflows/test-devices.yaml @@ -15,14 +15,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v7 + - uses: actions/cache@v5 with: path: | ~/.cache/pip ~/.platformio/.cache key: ${{ runner.os }}-pio - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v6 with: python-version: '3.9' - name: Install PlatformIO Core diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..9c988cc8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,77 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this is + +*Java Does USB* is a pure-Java USB library for communicating with USB devices using custom/vendor-specific protocols (not standard device classes like mass storage or HID). It accesses the OS's native USB APIs through the **Foreign Function and Memory API** — no JNI, no native third-party libraries. Requires **JDK 25** (the `pom.xml` targets release 25; older JDKs need older library versions, see README). + +The publishable library lives in `java-does-usb/`. The repo root also holds `examples/`, `test-devices/` (microcontroller firmware for the hardware test rig), `test-graalvm/` (GraalVM native-image compatibility check), and `reference/`. + +## Commands + +All library commands run from the `java-does-usb/` directory using the Maven wrapper (`./mvnw`). + +```bash +cd java-does-usb + +# Build & install to local Maven repo, skipping hardware tests +./mvnw clean install -DskipTests + +# Run all tests (REQUIRES a physical test device connected — see below) +./mvnw clean test + +# Run a single test class +./mvnw test -Dtest=BulkTransferTest + +# Run a single test method +./mvnw test -Dtest=BulkTransferTest#transferData + +# Build javadoc +./mvnw javadoc:javadoc +``` + +Examples are independent projects, each with its own `mvnw`/`gradlew`. Build one with `cd examples/ && ./mvnw clean compile` (or `./gradlew build` for Kotlin examples). + +### Native access flag + +Any code calling into the library needs native access enabled. Maven surefire passes `--enable-native-access=ALL-UNNAMED` automatically. When running from an IDE or standalone, add the VM option: +`--enable-native-access=net.codecrete.usb` (or `ALL-UNNAMED` if modules are ignored). + +## Testing requires hardware + +The unit tests are integration tests against a real USB device — they will fail with "No test device connected" without one. The device is built from an inexpensive STM32 board flashed with firmware from `test-devices/`: + +- **loopback-stm32** (VID `0xcafe`, PID `0xceaf`): supports all tests. +- **composite-stm32** (VID `0xcafe`, PID `0xcea0`): exercises composite-device handling; some tests are skipped. + +`TestDeviceConfig.java` hard-codes the VID/PID and endpoint numbers for both variants; `TestDeviceBase` auto-detects which one is connected. On Linux, a udev rule is needed for device access (see README "Linux" section). On Windows the test device auto-installs the WinUSB driver via WCID descriptors. + +The `continuous-integration.yaml` workflow only compiles the library and examples on all three OSes — it does **not** run the hardware tests. + +## Architecture + +### Cross-platform abstraction + +The public API is in package `net.codecrete.usb` (`Usb`, `UsbDevice`, `UsbInterface`, `UsbEndpoint`, exceptions, enums). It is the only exported package (`module-info.java`). + +`Usb.java` is the entry point. `Usb.instance()` lazily picks a platform implementation of `UsbDeviceRegistry` based on `os.name`/`os.arch` (Macos/Windows/Linux). Everything else flows through platform-specific subclasses of the abstractions in `net.codecrete.usb.common`: + +- `UsbDeviceRegistry` (common) — singleton that runs a background daemon thread enumerating devices and emitting connect/disconnect events. Each OS subclass implements `monitorDevices()` and calls `setInitialDeviceList()` when the first enumeration completes. +- `UsbDeviceImpl`, `UsbInterfaceImpl`, `UsbEndpointImpl`, `UsbAlternateInterfaceImpl` (common) — shared state and logic; each OS provides a `*UsbDevice` subclass that implements the actual native transfers. +- `EndpointInputStream`/`EndpointOutputStream` + platform `*EndpointInputStream`/`*EndpointOutputStream` — the high-throughput streaming layer. +- `Transfer`/`TransferCompletion` + platform `*Transfer` and `*AsyncTask` — asynchronous transfer plumbing (I/O completion ports on Windows, epoll on Linux, run loop on macOS). +- `ConfigurationParser` (common) — parses raw USB configuration descriptors (portable, byte-level; not OS-specific). + +When adding a feature, expect to touch the common abstraction plus **all three** platform implementations (`linux/`, `macos/`, `windows/`). + +### Native bindings (`gen` packages) + +Native API bindings live under `*/gen/` subpackages and are **generated code**, one package per shared library / macOS framework: + +- **Linux & macOS**: generated with [jextract](https://jdk.java.net/jextract/) via scripts in `java-does-usb/jextract/{linux,macos}/`. The generated code **is committed** to the repo (must be regenerated per-OS; it is portable across x64/ARM64 of the same OS). +- **Windows**: generated at build time by the `windowsapi-maven-plugin` (Windows API Generator) — the function/struct/constant list is configured in `pom.xml`, and the output is **not committed**. + +Some bindings are hand-written rather than generated, because jextract cannot capture thread-local error state (`errno` on Linux, `GetLastError()` on Windows) — those need an extra call-state parameter. See `java-does-usb/jextract/README.md` for the full generation process and jextract's quirks before regenerating. + +Standard USB descriptor structs (device/config/interface/endpoint/string descriptors, setup packet) are modeled in `net.codecrete.usb.usbstandard` as `MemorySegment` views — these are portable and shared across platforms. diff --git a/README.md b/README.md index efcd3b3d..6ee637da 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,10 @@ [![javadoc](https://javadoc.io/badge2/net.codecrete.usb/java-does-usb/javadoc.svg)](https://javadoc.io/doc/net.codecrete.usb/java-does-usb) -*Java Does USB* is a Java library for working with USB devices. It allows to query information about all conntected USB devices and to communicate with USB devices using custom / vendor specific protocols. (It is not intended for communication with standard types of USB devices such as mass storage devices, keyboards etc.) +*Java Does USB* is a Java library for working with USB devices. It allows you to query the connected USB devices and to communicate with them using custom / vendor-specific protocols. It is not intended for communication with standard types of USB devices such as mass storage devices, keyboards etc. -The library uses the [Foreign Function & Memory API](https://github.com/openjdk/panama-foreign) to access native APIs of the underlying operating system. It is written entirely in Java and does not need JNI or any native third-party library. The *Foreign Function & Memory API* (aka as project Panama) is currently in preview and will leave preview with Java 22. Currently, it can be used with Java 19, Java 20 or Java 21 (with preview features enabled). +The library uses the [Foreign Function and Memory API](https://docs.oracle.com/en/java/javase/22/core/foreign-function-and-memory-api.html) to access native APIs of the underlying operating system. It is written entirely in Java and does not use JNI or any native third-party library. The *Foreign Function and Memory API* has been introduced with Java 22. -*Note: The main branch and published versions ≥ 0.6.0 work with JDK 21 only. For JDK 20, use version 0.5.*. For JDK 19, use version 0.4.x. ## Features @@ -18,17 +17,8 @@ The library uses the [Foreign Function & Memory API](https://github.com/openjdk/ - Descriptive information about interfaces, settings and endpoints - High-throughput input/output streams - Support for alternate interface settings, composite devices and interface association -- Published on Maven Central +- Published on Maven Central and licensed under the permissive MIT license -### Planned - -- Isochronous transfer - -### Not planned - -- Changing configuration: The library selects the first configuration. Changing configurations is rarely used and not supported on Windows (limitation of WinUSB). -- USB 3.0 streams: Not supported on Windows (limitation of WinUSB). -- Providing information about USB buses, controllers and hubs ## Getting Started @@ -41,25 +31,25 @@ If you are using Maven, add the below dependency to your pom.xml: net.codecrete.usb java-does-usb - 0.6.0 + 1.3.0 ``` If you are using Gradle, add the below dependency to your build.gradle file: ```groovy -compile group: 'net.codecrete.usb', name: 'java-does-usb', version: '0.6.0' +compile group: 'net.codecrete.usb', name: 'java-does-usb', version: '1.3.0' ``` ```java package net.codecrete.usb.sample; -import net.codecrete.usb.USB; +import net.codecrete.usb.Usb; public class EnumerateDevices { public static void main(String[] args) { - for (var device : USB.getAllDevices()) { + for (var device : Usb.getDevices()) { System.out.println(device); } } @@ -67,26 +57,30 @@ public class EnumerateDevices { ``` + ## Documentation -- [Javadoc](https://javadoc.io/doc/net.codecrete.usb/java-does-usb) +- [Code Examples](https://github.com/manuelbl/JavaDoesUSB/wiki/Java-Does-USB-By-Examples) +- [Javadoc](https://javadoc.io/doc/net.codecrete.usb/java-does-usb) + ## Examples - [Bulk Transfer](examples/bulk_transfer/) demonstrates how to find a USB device, open it and communicate using bulk transfer. -- [Enumeration](examples/enumerate/) lists all connected USB devices and displays information about interfaces and endpoints. -- [Monitor](examples/monitor/) lists the connected USB devices and then monitors for USB devices being connected and disconnnected. +- Enumeration ([Java](examples/enumerate/) / [Kotlin](examples/enumerate_kotlin/)) lists all connected USB devices and displays information about interfaces and endpoints. +- Monitor ([Java](examples/monitor/) / [Kotlin](examples/monitor_kotlin/)) lists the connected USB devices and then monitors for devices being connected and disconnected. - [Device Firmware Upload (DFU) for STM32](examples/stm_dfu) uploads firmware to STM32 microcontrollers supporting the built-in DFU mode. - [ePaper Display](examples/epaper_display) communicates with an IT8951 controller for e-Paper displays and shows an image on the display. +- [Enumerate Native](examples/enumerate_native/) and [Monitor Native](examples/monitor_native/) demostrate how to build a native image with GraalVM. + ## Prerequisite -- Java 21, preview features enabled (available at https://www.azul.com/downloads/?package=jdk) -- Windows (x86 64-bit), macOS (x86 64-bit, ARM 64-bit) or Linux 64 bit (x86 64-bit, ARM 64-bit) +- Java 25 or higher +- Windows (x86 64-bit, ARM 64-bit), macOS (x86 64-bit, ARM 64-bit) or Linux 64 bit (x86 64-bit, ARM 64-bit) -For JDK 20, use the latest published version 0.5.x. For JDK 19, use the latest published version 0.4.x. ## Platform-specific Considerations @@ -94,16 +88,16 @@ For JDK 20, use the latest published version 0.5.x. For JDK 19, use the latest p ### macOS -No special considerations apply. Using this library, a Java application can connect to any USB device and claim any interfaces that isn't claimed by an operating system driver or another application. Standard operation-system drivers can be unloaded if the application is run with root privileges. +No special considerations apply. Using this library, a Java application can connect to any USB device and claim any interface that isn't claimed by an operating system driver or another application. Standard operating system drivers can be unloaded if the application is run with *root* privileges. It runs both on Macs with Apple Silicon and Intel processors. ### Linux -*libudev* is used to discover and monitor USB devices. It is closely tied to *systemd*. So the library only runs on Linux distributions with *systemd* and the related libraries. The majority of Linux distributions suitable for desktop computing (as opposed to distributions optimized for containers) fulfill this requirement. +*libudev* is used to discover and monitor USB devices. It is closely tied to *systemd*. So the library runs on Linux distributions with *systemd* and the related libraries. The majority of Linux distributions suitable for desktop computing (as opposed to distributions optimized for containers) fulfill this requirement. It runs on both Intel/AMD and ARM processors. -Similar to macOS, a Java application can connect to any USB device and claim any interfaces that isn't claimed by an operating system driver or another application. Standard operation system drivers can be unloaded (without the need for root privileges). +Similar to macOS, a Java application can connect to any USB device and claim any interface that isn't claimed by an operating system driver or another application. Standard operating system drivers can be unloaded (without the need for root privileges). -Most Linux distributions by default set up user accounts without permissions to access USB devices directly. The *udev* system daemon is responsible for assigning permissions to USB devices. It can be configured to assign specific permissions or ownership: +Most Linux distributions set up user accounts without permissions to access USB devices. The *udev* system daemon is responsible for assigning permissions to USB devices. It can be configured to assign specific permissions or ownership: Create a file called `/etc/udev/rules.d/80-javadoesusb-udev.rules` with the below content: @@ -113,48 +107,66 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="cafe", MODE="0666" This adds the rule to assign permission mode 0666 to all USB devices with vendor ID `0xCAFE`. This unregistered vendor ID is used by the test devices. +Without the *udev* rule, it is still possible to enumerate and query all USB devices. + ### Windows -The Windows driver model is more rigid than the ones of macOS or Linux. It's not possible to open any USB device that is not claimed. Instead, only devices using the *WinUSB* driver can be opened. This even applies to devices with no installed driver. +The Windows driver model is rather rigid. It's not possible to open a USB device unless it uses the *WinUSB* driver. This even applies to devices with no installed driver. Enumerating and querying USB devices is possible independent of the driver. -USB devices can implement certain control requests to instruct Windows to automatically install the WinUSB driver (search for *WCID* or *Microsoft OS Compatibility Descriptors*). The WinUSB driver can also be manually installed or replaced using a software called [Zadig](https://zadig.akeo.ie/). +USB devices can implement special control requests to instruct Windows to automatically install the WinUSB driver (search for *WCID* or *Microsoft OS Compatibility Descriptors*). The WinUSB driver can also be manually installed or replaced using a tool called [Zadig](https://zadig.akeo.ie/). The test devices implement the required control requests. So the driver is installed automatically. -The library has not been tested on Windows for ARM64. It might or might not work. - +The implementation runs on both Windows for Intel/AMD and ARM processors. -### 32-bit versions -The Foreign Function & Memory API has not been implemented for 32-bit operating systems / JDKs (and likely never will be). +## Building from source +To build from source, run the following command: -## Code generation +``` +cd java-does-usb +mvn clean install -DskipTests +``` -Many bindings for the native APIs have been generated with *jextract*. See the [jextract](java-does-usb/jextract) subdirectory for more information. +The tests are skipped as they require that a special test device is connected to the computer. See the next section for more information. ## Testing -In order to run the unit tests, a special test device must be connected to the computer. See the [loopback-stm32](test-devices/loopback-stm32) directory. +In order to run the unit tests, a special test device must be connected to the computer, which can be easily created from very inexpensive microcontroller boards. Two variants exist: + +- [loopback-stm32](test-devices/loopback-stm32) +- [composite-stm32](test-devices/composite-stm32) + +The test device with the *loopback-stm32* code supports all tests. If the test device with the *composite-stm32* code is connected, some tests are skipped, but the correct handling of composite devices is verified instead. Tests can be run from the command line: ``` +cd java-does-usb mvn clean test ``` -If they are run from an IDE (such as IntelliJ IDEA), you must likely configure VM options to enable preview features and allow native access: +If they are run from an IDE (such as IntelliJ IDEA), you will likely need to configure VM options to allow native access: ``` ---enable-preview --enable-native-access=net.codecrete.usb +--enable-native-access=net.codecrete.usb ``` Or (if modules are ignored): ``` ---enable-preview --enable-native-access=ALL-UNNAMED +--enable-native-access=ALL-UNNAMED ``` + + + +## Code generation + +Many bindings for the native APIs have been generated with *jextract*. See the [jextract](java-does-usb/jextract) subdirectory for more information. For functions that need to retain the error state (`errno` on Linux, `GetLastError()` on Windows), the bindings have been manually written as *jextract* does not support it. + +Since the code can only be generated for the current operating system, it must be generated on separate computers for Linux, Windows and macOS. Thus, the generated code is included in the repository. The generated code is compilable on all operating systems. diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..3e3511a0 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,100 @@ +# Releasing Java Does USB + +This document describes how a new version of the library is released to Maven Central, and how +version numbers flow through the repository afterwards. + +## Versioning scheme + +- The library follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`). +- On the `main` branch, `java-does-usb/pom.xml` always carries the *next*, unreleased version + with a `-SNAPSHOT` suffix (e.g. `1.2.2-SNAPSHOT`). This makes it obvious that a build from `main` + is a development build, not something published to Central. +- `README.md` and the example projects under `examples/` intentionally do **not** track this + SNAPSHOT. They pin the latest *released* version, because they double as user-facing + documentation: a user reading the README or copying an example's `pom.xml`/`build.gradle.kts` + should see the version they can actually `mvn install` from Central today. +- Continuous integration overrides the pinned example version at build time so it still compiles + the examples against `main`'s HEAD (see "How CI stays honest" below). No file needs to be edited + for this to work. + +## Release checklist + +1. **Drop the `-SNAPSHOT` suffix.** + In `java-does-usb/pom.xml`, set `` to the release version, e.g.: + ```bash + cd java-does-usb + ./mvnw versions:set -DnewVersion=1.3.1 -DgenerateBackupPoms=false + ``` + +2. **Update the version everywhere it's pinned for users.** This means: + - `README.md` — the Maven (`...`) and Gradle (`version: '...'`) snippets + under "Getting Started", and the version history table if you're adding an entry. + - Every example's dependency on `java-does-usb`, pinned via a single property so it's one edit + per file (`java-does-usb.version` in the Maven examples, `javaDoesUsbVersion` in the Gradle + one): + - `examples/enumerate/pom.xml` + - `examples/bulk_transfer/pom.xml` + - `examples/monitor/pom.xml` + - `examples/monitor_kotlin/pom.xml` + - `examples/stm_dfu/pom.xml` + - `examples/epaper_display/pom.xml` + - `examples/enumerate_native/pom.xml` + - `examples/monitor_native/pom.xml` + - `examples/enumerate_kotlin/build.gradle.kts` + - The example's *own* project version (its `` / `version = "..."`, separate from the + `java-does-usb.version`/`javaDoesUsbVersion` property), which by convention tracks the library + release it was last verified against, for `enumerate`, `bulk_transfer`, `monitor`, + `monitor_kotlin`, `stm_dfu`, `epaper_display`, and `enumerate_kotlin`. (`enumerate_native` and + `monitor_native` version themselves independently as `1.0-SNAPSHOT` and don't need this.) + - The sample console output hardcoded in each example's own `README.md` (e.g. build log lines + like `[INFO] Building enumerate 1.2.1` or jar filenames like `stm_dfu-1.2.1.jar`), which + embeds the example's own project version from the point above. + + A simple search for the previous version number across `README.md` and `examples/` will locate + every occurrence listed above. + +3. **Commit, tag, and publish.** + ```bash + git add -A + git commit -m "Release 1.2.2" + git tag v1.2.2 + git push origin main v1.2.2 + cd java-does-usb + ./mvnw clean install # GPG passphrase from password store + ./mvnw clean deploy + ``` + +4. **Prepare `main` for the next development iteration.** + ```bash + cd java-does-usb + ./mvnw versions:set -DnewVersion=1.2.3-SNAPSHOT -DgenerateBackupPoms=false + git add pom.xml + git commit -m "Prepare for next development iteration" + git push origin main + ``` + Deliberately do **not** touch `README.md` or the examples in this step — they should keep + pointing at the release just made (1.2.2) until the *next* release checklist run. + +## How CI stays honest + +Because the examples pin the released version, a naive CI setup would silently compile them +against whatever is available on Maven Central instead of the code actually being tested — i.e. +after step 4 above, `main` might contain a breaking change that no CI run would ever catch until +the next release. + +To prevent that, `.github/workflows/continuous-integration.yaml`: + +1. Builds and `install`s the library from the checked-out `pom.xml` (whatever version — released + or `-SNAPSHOT` — is on HEAD) into the local Maven repository. +2. Reads that exact version back out with `mvn help:evaluate -Dexpression=project.version`. +3. Passes it to each example build as an override: + - Maven examples: `-Djava-does-usb.version=` + - The Gradle example (`enumerate_kotlin`): `-PjavaDoesUsbVersion=` + +This means CI always compiles every example against the exact commit under test, while the +committed example files keep showing users the last real release. + +If you add a new example, give its `java-does-usb` dependency the same treatment: introduce a +`java-does-usb.version` property (Maven) or an overridable `javaDoesUsbVersion` val (Gradle) +defaulting to the current released version, add a CI step following the existing pattern, and add +it to the list in step 2 of the release checklist above. diff --git a/examples/bulk_transfer/.mvn/wrapper/maven-wrapper.properties b/examples/bulk_transfer/.mvn/wrapper/maven-wrapper.properties index 6d3a5665..f3283b08 100644 --- a/examples/bulk_transfer/.mvn/wrapper/maven-wrapper.properties +++ b/examples/bulk_transfer/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/examples/bulk_transfer/README.md b/examples/bulk_transfer/README.md index b7f63b11..83b4d92e 100644 --- a/examples/bulk_transfer/README.md +++ b/examples/bulk_transfer/README.md @@ -4,16 +4,16 @@ This sample shows how to find a device, open it and transfer data from and to bu ## Prerequisites -- Java 20 +- Java 22 - Apache Maven - 64-bit operating system (Windows, macOS, Linux) - A USB device with bulk IN and OUT endpoints (e.g. the test device, see https://github.com/manuelbl/JavaDoesUSB/tree/main/test-devices/loopback-stm32) ## How to run -### Install Java 20 +### Install Java 22 or higher -Check that *Java 20* is installed: +Check that Java 22 or higher is installed: ```shell $ java -version @@ -39,24 +39,22 @@ $ mvn compile exec:exec [INFO] Scanning for projects... [INFO] [INFO] --------------< net.codecrete.usb.examples:bulk-transfer >-------------- -[INFO] Building bulk-transfer 0.5.1 +[INFO] Building bulk-transfer 1.3.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] -[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ bulk-transfer --- -[INFO] Using 'UTF-8' encoding to copy filtered resources. -[INFO] skip non existing resourceDirectory /Users/me/Documents/JavaDoesUSB/examples/bulk_transfer/src/main/resources +[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ bulk-transfer --- +[INFO] skip non existing resourceDirectory /home/user/Documents/JavaDoesUSB/examples/bulk_transfer/src/main/resources [INFO] -[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ bulk-transfer --- -[INFO] Changes detected - recompiling the module! -[INFO] Compiling 1 source file to /Users/me/Documents/JavaDoesUSB/examples/bulk_transfer/target/classes +[INFO] --- maven-compiler-plugin:3.12.1:compile (default-compile) @ bulk-transfer --- +[INFO] Nothing to compile - all classes are up to date. [INFO] -[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ bulk-transfer --- +[INFO] --- exec-maven-plugin:3.1.1:exec (default-cli) @ bulk-transfer --- 6 bytes sent. 6 bytes received. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ -[INFO] Total time: 1.259 s -[INFO] Finished at: 2023-03-23T14:10:17+01:00 +[INFO] Total time: 1.228 s +[INFO] Finished at: 2024-10-13T16:23:29+01:00 [INFO] ------------------------------------------------------------------------ ``` diff --git a/examples/bulk_transfer/mvnw.cmd b/examples/bulk_transfer/mvnw.cmd index c4586b56..f80fbad3 100644 --- a/examples/bulk_transfer/mvnw.cmd +++ b/examples/bulk_transfer/mvnw.cmd @@ -1,205 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/examples/bulk_transfer/pom.xml b/examples/bulk_transfer/pom.xml index ca51c5b7..e6734349 100644 --- a/examples/bulk_transfer/pom.xml +++ b/examples/bulk_transfer/pom.xml @@ -6,86 +6,83 @@ net.codecrete.usb.examples bulk-transfer - 0.6.0-SNAPSHOT + 1.3.0 bulk-transfer https://github.com/manuelbl/JavaDoesUSB/examples/bulk_transfer UTF-8 - 21 - 21 + 22 + 22 + 1.3.0 net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + ${java-does-usb.version} - + maven-clean-plugin - 3.1.0 + 3.3.2 maven-resources-plugin - 3.0.2 + 3.3.1 maven-compiler-plugin - 3.8.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 22 + 22 + 22 maven-surefire-plugin - 2.22.1 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED maven-jar-plugin - 3.0.2 + 3.3.0 maven-install-plugin - 2.5.2 + 3.1.1 maven-deploy-plugin - 2.8.2 + 3.1.1 maven-site-plugin - 3.7.1 + 3.12.1 maven-project-info-reports-plugin - 3.0.0 + 3.5.0 org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.1.1 java - --enable-preview --enable-native-access=ALL-UNNAMED -classpath diff --git a/examples/bulk_transfer/src/main/java/net/codecrete/usb/examples/BulkTransfer.java b/examples/bulk_transfer/src/main/java/net/codecrete/usb/examples/BulkTransfer.java index bfef6131..4e738ef7 100644 --- a/examples/bulk_transfer/src/main/java/net/codecrete/usb/examples/BulkTransfer.java +++ b/examples/bulk_transfer/src/main/java/net/codecrete/usb/examples/BulkTransfer.java @@ -27,7 +27,7 @@ public class BulkTransfer { private static final int ENDPOINT_IN = 2; public static void main(String[] args) { - var optionalDevice = USB.getDevice(VID, PID); + var optionalDevice = Usb.findDevice(VID, PID); if (optionalDevice.isEmpty()) { System.out.printf("No USB device with VID=0x%04x and PID=0x%04x found.%n", VID, PID); return; diff --git a/examples/enumerate/.mvn/wrapper/maven-wrapper.properties b/examples/enumerate/.mvn/wrapper/maven-wrapper.properties index 6d3a5665..f3283b08 100644 --- a/examples/enumerate/.mvn/wrapper/maven-wrapper.properties +++ b/examples/enumerate/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/examples/enumerate/README.md b/examples/enumerate/README.md index 78867753..42683a15 100644 --- a/examples/enumerate/README.md +++ b/examples/enumerate/README.md @@ -4,15 +4,15 @@ This sample enumerates the connected USB devices and provides information about ## Prerequisites -- Java 20 +- Java 22 - Apache Maven - 64-bit operating system (Windows, macOS, Linux) ## How to run -### Install Java 20 +### Install Java 22 or higher -Check that *Java 20* is installed: +Check that Java 22 or higher is installed: ```shell $ java -version @@ -38,22 +38,21 @@ $ mvn compile exec:exec [INFO] Scanning for projects... [INFO] [INFO] ----------------< net.codecrete.usb.examples:enumerate >---------------- -[INFO] Building enumerate 0.5.1 +[INFO] Building enumerate 1.3.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] -[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ enumerate --- -[INFO] Using 'UTF-8' encoding to copy filtered resources. -[INFO] skip non existing resourceDirectory /Users/me/Documents/JavaDoesUSB/examples/enumerate/src/main/resources +[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ enumerate --- +[INFO] Copying 1 resource from src/main/resources to target/classes [INFO] -[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ enumerate --- -[INFO] Changes detected - recompiling the module! -[INFO] Compiling 2 source files to /Users/me/Documents/JavaDoesUSB/examples/enumerate/target/classes +[INFO] --- maven-compiler-plugin:3.12.1:compile (default-compile) @ enumerate --- +[INFO] Nothing to compile - all classes are up to date. [INFO] -[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ enumerate --- +[INFO] --- exec-maven-plugin:3.1.1:exec (default-cli) @ enumerate --- Device: VID: 0xcafe PID: 0xceaf Manufacturer: JavaDoesUSB Product name: Loopback + Serial number: 35A737883336 ... ``` diff --git a/examples/enumerate/mvnw.cmd b/examples/enumerate/mvnw.cmd index c4586b56..f80fbad3 100644 --- a/examples/enumerate/mvnw.cmd +++ b/examples/enumerate/mvnw.cmd @@ -1,205 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/examples/enumerate/pom.xml b/examples/enumerate/pom.xml index 34048b3f..07c06829 100644 --- a/examples/enumerate/pom.xml +++ b/examples/enumerate/pom.xml @@ -6,22 +6,23 @@ net.codecrete.usb.examples enumerate - 0.6.0-SNAPSHOT + 1.3.0 enumerate https://github.com/manuelbl/JavaDoesUSB/examples/enumerate UTF-8 - 21 - 21 + 22 + 22 + 1.3.0 net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + ${java-does-usb.version} org.tinylog @@ -41,66 +42,62 @@ - + maven-clean-plugin - 3.1.0 + 3.3.2 maven-resources-plugin - 3.0.2 + 3.3.1 maven-compiler-plugin - 3.8.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 22 + 22 + 22 maven-surefire-plugin - 2.22.1 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED maven-jar-plugin - 3.0.2 + 3.3.0 maven-install-plugin - 2.5.2 + 3.1.1 maven-deploy-plugin - 2.8.2 + 3.1.1 maven-site-plugin - 3.7.1 + 3.12.1 maven-project-info-reports-plugin - 3.0.0 + 3.5.0 org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.1.1 java - --enable-preview --enable-native-access=ALL-UNNAMED -classpath diff --git a/examples/enumerate/src/main/java/net/codecrete/usb/examples/Enumerate.java b/examples/enumerate/src/main/java/net/codecrete/usb/examples/Enumerate.java index b575db86..4e387b8f 100644 --- a/examples/enumerate/src/main/java/net/codecrete/usb/examples/Enumerate.java +++ b/examples/enumerate/src/main/java/net/codecrete/usb/examples/Enumerate.java @@ -19,32 +19,32 @@ public class Enumerate { public static void main(String[] args) { // display the already present USB devices - for (var device : USB.getAllDevices()) + for (var device : Usb.getDevices()) printDevice(device); } - private static void printDevice(USBDevice device) { + private static void printDevice(UsbDevice device) { System.out.println("Device:"); - System.out.printf(" VID: 0x%04x%n", device.vendorId()); - System.out.printf(" PID: 0x%04x%n", device.productId()); - if (device.manufacturer() != null) - System.out.printf(" Manufacturer: %s%n", device.manufacturer()); - if (device.product() != null) - System.out.printf(" Product name: %s%n", device.product()); - if (device.serialNumber() != null) - System.out.printf(" Serial number: %s%n", device.serialNumber()); - System.out.printf(" Device class: 0x%02x", device.classCode()); - printInParens(USBClassInfo.lookupClass(device.classCode())); - System.out.printf(" Device subclass: 0x%02x", device.subclassCode()); - printInParens(USBClassInfo.lookupSubclass(device.classCode(), device.subclassCode())); - System.out.printf(" Device protocol: 0x%02x", device.protocolCode()); - printInParens(USBClassInfo.lookupProtocol(device.classCode(), device.subclassCode(), device.protocolCode())); - - for (var intf: device.interfaces()) + System.out.printf(" VID: 0x%04x%n", device.getVendorId()); + System.out.printf(" PID: 0x%04x%n", device.getProductId()); + if (device.getManufacturer() != null) + System.out.printf(" Manufacturer: %s%n", device.getManufacturer()); + if (device.getProduct() != null) + System.out.printf(" Product name: %s%n", device.getProduct()); + if (device.getSerialNumber() != null) + System.out.printf(" Serial number: %s%n", device.getSerialNumber()); + System.out.printf(" Device class: 0x%02x", device.getClassCode()); + printInParens(USBClassInfo.lookupClass(device.getClassCode())); + System.out.printf(" Device subclass: 0x%02x", device.getSubclassCode()); + printInParens(USBClassInfo.lookupSubclass(device.getClassCode(), device.getSubclassCode())); + System.out.printf(" Device protocol: 0x%02x", device.getProtocolCode()); + printInParens(USBClassInfo.lookupProtocol(device.getClassCode(), device.getSubclassCode(), device.getProtocolCode())); + + for (var intf: device.getInterfaces()) printInterface(intf); - printRawDescriptor("Device descriptor", device.deviceDescriptor()); - printRawDescriptor("Configuration descriptor", device.configurationDescriptor()); + printRawDescriptor("Device descriptor", device.getDeviceDescriptor()); + printRawDescriptor("Configuration descriptor", device.getConfigurationDescriptor()); System.out.println(); System.out.println(); @@ -59,36 +59,36 @@ private static void printInParens(Optional text) { } } - private static void printInterface(USBInterface intf) { - for (var alt : intf.alternates()) - printAlternate(alt, intf.number(), alt == intf.alternate()); + private static void printInterface(UsbInterface intf) { + for (var alt : intf.getAlternates()) + printAlternate(alt, intf.getNumber(), alt == intf.getCurrentAlternate()); } - private static void printAlternate(USBAlternateInterface alt, int intferaceNumber, boolean isDefault) { + private static void printAlternate(UsbAlternateInterface alt, int intferaceNumber, boolean isDefault) { System.out.println(); if (isDefault) { System.out.printf(" Interface %d%n", intferaceNumber); } else { - System.out.printf(" Interface %d (alternate %d)%n", intferaceNumber, alt.number()); + System.out.printf(" Interface %d (alternate %d)%n", intferaceNumber, alt.getNumber()); } - System.out.printf(" Interface class: 0x%02x", alt.classCode()); - printInParens(USBClassInfo.lookupClass(alt.classCode())); - System.out.printf(" Interface subclass: 0x%02x", alt.subclassCode()); - printInParens(USBClassInfo.lookupProtocol(alt.classCode(), alt.subclassCode(), alt.protocolCode())); - System.out.printf(" Interface protocol: 0x%02x", alt.protocolCode()); - printInParens(USBClassInfo.lookupProtocol(alt.classCode(), alt.subclassCode(), alt.protocolCode())); + System.out.printf(" Interface class: 0x%02x", alt.getClassCode()); + printInParens(USBClassInfo.lookupClass(alt.getClassCode())); + System.out.printf(" Interface subclass: 0x%02x", alt.getSubclassCode()); + printInParens(USBClassInfo.lookupProtocol(alt.getClassCode(), alt.getSubclassCode(), alt.getProtocolCode())); + System.out.printf(" Interface protocol: 0x%02x", alt.getProtocolCode()); + printInParens(USBClassInfo.lookupProtocol(alt.getClassCode(), alt.getSubclassCode(), alt.getProtocolCode())); - for (var endpoint : alt.endpoints()) + for (var endpoint : alt.getEndpoints()) printEndpoint(endpoint); } - private static void printEndpoint(USBEndpoint endpoint) { + private static void printEndpoint(UsbEndpoint endpoint) { System.out.println(); - System.out.printf(" Endpoint %d%n", endpoint.number()); - System.out.printf(" Direction: %s%n", endpoint.direction().name()); - System.out.printf(" Transfer type: %s%n", endpoint.transferType().name()); - System.out.printf(" Packet size: %d bytes%n", endpoint.packetSize()); + System.out.printf(" Endpoint %d%n", endpoint.getNumber()); + System.out.printf(" Direction: %s%n", endpoint.getDirection().name()); + System.out.printf(" Transfer type: %s%n", endpoint.getTransferType().name()); + System.out.printf(" Packet size: %d bytes%n", endpoint.getPacketSize()); } private static void printRawDescriptor(String title, byte[] descriptor) { diff --git a/examples/enumerate_kotlin/.gitignore b/examples/enumerate_kotlin/.gitignore new file mode 100644 index 00000000..b1dff0dd --- /dev/null +++ b/examples/enumerate_kotlin/.gitignore @@ -0,0 +1,45 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Kotlin ### +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/examples/enumerate_kotlin/README.md b/examples/enumerate_kotlin/README.md new file mode 100644 index 00000000..63418d03 --- /dev/null +++ b/examples/enumerate_kotlin/README.md @@ -0,0 +1,44 @@ +# USB Device Enumeration (Kotlin) + +This sample enumerates the connected USB devices and provides information about the interfaces and endpoints. + +## Prerequisites + +- Java 25 +- Gradle +- 64-bit operating system (Windows, macOS, Linux) + +## How to run + +### Install Java 25 or higher + +Check that Java 25 or higher is installed: + +```shell +$ java -version +``` + +If not, download and install it, e.g. from [Azul](https://www.azul.com/downloads/?package=jdk). + +### Install Maven + +Check that *Maven* is installed: + +```shell +$ gradle -version +``` + +If it is not present, install it, typically using package manager like *Homebrew* on macOS, *Chocolately* on Windows and *apt* on Linux. + +### Build and run the program + +```shell +$ cd JavaDoesUSB/examples/enumerate_kotlin +$ gradle run +Device: + VID: 0xcafe + PID: 0xceaf + Manufacturer: JavaDoesUSB + Product name: Loopback +... +``` diff --git a/examples/enumerate_kotlin/build.gradle.kts b/examples/enumerate_kotlin/build.gradle.kts new file mode 100644 index 00000000..6d836d13 --- /dev/null +++ b/examples/enumerate_kotlin/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + kotlin("jvm") version "2.3.21" + application +} + +group = "net.codecrete.usb.examples" +version = "1.3.0" + +val javaDoesUsbVersion = (findProperty("javaDoesUsbVersion") as String?) ?: "1.3.0" +val tinyLogVersion = "2.7.0" + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("net.codecrete.usb:java-does-usb:$javaDoesUsbVersion") + implementation("org.tinylog:tinylog-api:$tinyLogVersion") + implementation("org.tinylog:tinylog-impl:$tinyLogVersion") + implementation("org.tinylog:jsl-tinylog:$tinyLogVersion") + + testImplementation(kotlin("test")) +} + +kotlin { + jvmToolchain(25) +} + +application { + mainClass = "net.codecrete.usb.examples.EnumerateKt" + applicationDefaultJvmArgs = listOf("--enable-native-access=ALL-UNNAMED") +} + +tasks.test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/examples/enumerate_kotlin/gradle.properties b/examples/enumerate_kotlin/gradle.properties new file mode 100644 index 00000000..2610d58f --- /dev/null +++ b/examples/enumerate_kotlin/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +org.gradle.configuration-cache=true diff --git a/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.jar b/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..b1b8ef56 Binary files /dev/null and b/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.properties b/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..df6a6ad7 --- /dev/null +++ b/examples/enumerate_kotlin/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,9 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/examples/enumerate_kotlin/gradlew b/examples/enumerate_kotlin/gradlew new file mode 100755 index 00000000..b9bb139f --- /dev/null +++ b/examples/enumerate_kotlin/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/enumerate_kotlin/gradlew.bat b/examples/enumerate_kotlin/gradlew.bat new file mode 100644 index 00000000..24c62d56 --- /dev/null +++ b/examples/enumerate_kotlin/gradlew.bat @@ -0,0 +1,82 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/examples/enumerate_kotlin/settings.gradle.kts b/examples/enumerate_kotlin/settings.gradle.kts new file mode 100644 index 00000000..d48b99a0 --- /dev/null +++ b/examples/enumerate_kotlin/settings.gradle.kts @@ -0,0 +1,4 @@ +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} +rootProject.name = "enumerate" \ No newline at end of file diff --git a/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/Enumerate.kt b/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/Enumerate.kt new file mode 100644 index 00000000..1d15c964 --- /dev/null +++ b/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/Enumerate.kt @@ -0,0 +1,95 @@ +package net.codecrete.usb.examples + +import net.codecrete.usb.* +import kotlin.math.min + + +fun main() { + Enumerate().enumerate() +} + +class Enumerate { + + private var classInfo = UsbClassInfo() + + fun enumerate() { + for (device in Usb.getDevices()) { + printDevice(device) + } + } + + private fun printDevice(device: UsbDevice) { + println("Device:") + System.out.printf(" VID: 0x%04x%n", device.vendorId) + System.out.printf(" PID: 0x%04x%n", device.productId) + if (device.manufacturer != null) System.out.printf(" Manufacturer: %s%n", device.manufacturer) + if (device.product != null) System.out.printf(" Product name: %s%n", device.product) + if (device.serialNumber != null) System.out.printf(" Serial number: %s%n", device.serialNumber) + System.out.printf(" Device class: 0x%02x", device.classCode) + printInParens(classInfo.lookupClass(device.classCode)) + System.out.printf(" Device subclass: 0x%02x", device.subclassCode) + printInParens(classInfo.lookupSubclass(device.classCode, device.subclassCode)) + System.out.printf(" Device protocol: 0x%02x", device.protocolCode) + printInParens(classInfo.lookupProtocol(device.classCode, device.subclassCode, device.protocolCode)) + for (intf in device.interfaces) printInterface(intf) + printRawDescriptor("Device descriptor", device.deviceDescriptor) + printRawDescriptor("Configuration descriptor", device.configurationDescriptor) + println() + println() + } + + private fun printInParens(text: String?) { + if (text != null) { + System.out.printf(" (%s)%n", text) + } else { + println() + } + } + + private fun printInterface(intf: UsbInterface) { + for (alt in intf.alternates) printAlternate(alt, intf.number, alt === intf.currentAlternate) + } + + private fun printAlternate(alt: UsbAlternateInterface, intferfaceNumber: Int, isDefault: Boolean) { + println() + if (isDefault) { + System.out.printf(" Interface %d%n", intferfaceNumber) + } else { + System.out.printf(" Interface %d (alternate %d)%n", intferfaceNumber, alt.number) + } + System.out.printf(" Interface class: 0x%02x", alt.classCode) + printInParens(classInfo.lookupClass(alt.classCode)) + System.out.printf(" Interface subclass: 0x%02x", alt.subclassCode) + printInParens(classInfo.lookupProtocol(alt.classCode, alt.subclassCode, alt.protocolCode)) + System.out.printf(" Interface protocol: 0x%02x", alt.protocolCode) + printInParens(classInfo.lookupProtocol(alt.classCode, alt.subclassCode, alt.protocolCode)) + for (endpoint in alt.endpoints) + printEndpoint(endpoint) + } + + private fun printEndpoint(endpoint: UsbEndpoint) { + println() + System.out.printf(" Endpoint %d%n", endpoint.number) + System.out.printf(" Direction: %s%n", endpoint.direction.name) + System.out.printf(" Transfer type: %s%n", endpoint.transferType.name) + System.out.printf(" Packet size: %d bytes%n", endpoint.packetSize) + } + + private fun printRawDescriptor(title: String, descriptor: ByteArray) { + println() + println(title) + val len = descriptor.size + var i = 0 + while (i < len) { + System.out.printf("%04x ", i) + var j = i + while (j < min(i + 16, len)) { + System.out.printf(" %02x", descriptor[j].toInt() and 255) + j += 1 + } + println() + i += 16 + } + } + +} diff --git a/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/UsbClassInfo.kt b/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/UsbClassInfo.kt new file mode 100644 index 00000000..56ee48dc --- /dev/null +++ b/examples/enumerate_kotlin/src/main/kotlin/net/codecrete/usb/examples/UsbClassInfo.kt @@ -0,0 +1,234 @@ +package net.codecrete.usb.examples + +import java.io.BufferedReader +import java.io.IOException +import java.io.StringReader +import java.util.* + + +class UsbClassInfo { + private val classCodes: MutableList = ArrayList() + private val subclassCodes: MutableList = ArrayList() + private val protocolCodes: MutableList = ArrayList() + + // List of known device classes, subclasses and + // from http://www.linux-usb.org/usb.ids + private val rawClassData = """ +C 00 (Defined at Interface level) +C 01 Audio + 01 Control Device + 02 Streaming + 03 MIDI Streaming +C 02 Communications + 01 Direct Line + 02 Abstract (modem) + 00 None + 01 AT-commands (v.25ter) + 02 AT-commands (PCCA101) + 03 AT-commands (PCCA101 + wakeup) + 04 AT-commands (GSM) + 05 AT-commands (3G) + 06 AT-commands (CDMA) + fe Defined by command set descriptor + ff Vendor Specific (MSFT RNDIS?) + 03 Telephone + 04 Multi-Channel + 05 CAPI Control + 06 Ethernet Networking + 07 ATM Networking + 08 Wireless Handset Control + 09 Device Management + 0a Mobile Direct Line + 0b OBEX + 0c Ethernet Emulation + 07 Ethernet Emulation (EEM) +C 03 Human Interface Device + 00 No Subclass + 00 None + 01 Keyboard + 02 Mouse + 01 Boot Interface Subclass + 00 None + 01 Keyboard + 02 Mouse +C 05 Physical Interface Device +C 06 Imaging + 01 Still Image Capture + 01 Picture Transfer Protocol (PIMA 15470) +C 07 Printer + 01 Printer + 00 Reserved/Undefined + 01 Unidirectional + 02 Bidirectional + 03 IEEE 1284.4 compatible bidirectional + ff Vendor Specific +C 08 Mass Storage + 01 RBC (typically Flash) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only + 02 SFF-8020i, MMC-2 (ATAPI) + 03 QIC-157 + 04 Floppy (UFI) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only + 05 SFF-8070i + 06 SCSI + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only +C 09 Hub + 00 Unused + 00 Full speed (or root) hub + 01 Single TT + 02 TT per port +C 0a CDC Data + 00 Unused + 30 I.430 ISDN BRI + 31 HDLC + 32 Transparent + 50 Q.921M + 51 Q.921 + 52 Q.921TM + 90 V.42bis + 91 Q.932 EuroISDN + 92 V.120 V.24 rate ISDN + 93 CAPI 2.0 + fd Host Based Driver + fe CDC PUF + ff Vendor specific +C 0b Chip/SmartCard +C 0d Content Security +C 0e Video + 00 Undefined + 01 Video Control + 02 Video Streaming + 03 Video Interface Collection +C 58 Xbox + 42 Controller +C dc Diagnostic + 01 Reprogrammable Diagnostics + 01 USB2 Compliance +C e0 Wireless + 01 Radio Frequency + 01 Bluetooth + 02 Ultra WideBand Radio Control + 03 RNDIS + 02 Wireless USB Wire Adapter + 01 Host Wire Adapter Control/Data Streaming + 02 Device Wire Adapter Control/Data Streaming + 03 Device Wire Adapter Isochronous Streaming +C ef Miscellaneous Device + 01 ? + 01 Microsoft ActiveSync + 02 Palm Sync + 02 ? + 01 Interface Association + 02 Wire Adapter Multifunction Peripheral + 03 ? + 01 Cable Based Association + 05 USB3 Vision +C fe Application Specific Interface + 01 Device Firmware Update + 02 IRDA Bridge + 03 Test and Measurement + 01 TMC + 02 USB488 +C ff Vendor Specific Class + ff Vendor Specific Subclass + ff Vendor Specific Protocol + """.trimIndent() + + + /** + * Provides the name of the specified USB class. + * + * @param classCode the USB class code + * @return an optional name + */ + fun lookupClass(classCode: Int): String? { + loadData() + return classCodes + .filter { cc -> cc.classCode == classCode } + .map { cc -> cc.name } + .firstOrNull() + } + + /** + * Provides the name of the specified USB subclass. + * + * @param classCode the USB class code + * @param subclassCode the USB subclass code + * @return an optional name + */ + fun lookupSubclass(classCode: Int, subclassCode: Int): String? { + loadData() + return subclassCodes + .filter { scc -> scc.classCode == classCode && scc.subclassCode == subclassCode } + .map { scc -> scc.name } + .firstOrNull() + } + + /** + * Provides the name of the specified USB protocol. + * + * @param classCode the USB class code + * @param subclassCode the USB subclass code + * @param protocolCode the USB protocol code + * @return an optional name + */ + fun lookupProtocol(classCode: Int, subclassCode: Int, protocolCode: Int): String? { + loadData() + return protocolCodes + .filter { prot -> prot.classCode == classCode && prot.subclassCode == subclassCode && prot.protocolCode == protocolCode } + .map { prot -> prot.name } + .firstOrNull() + } + + private fun loadData() { + if (classCodes.isNotEmpty()) + return + + try { + StringReader(rawClassData).use { stringReader -> + BufferedReader(stringReader).use { reader -> + var classCode = 0 + var subclassCode = 0 + var line = reader.readLine() + while (line != null) { + // protocol line + when { + line.startsWith("\t\t") -> { + val protocol = line.substring(2, 4).toInt(16) + protocolCodes.add(ProtocolCode(classCode, subclassCode, protocol, line.substring(6))) + // subclass line + } + line.startsWith("\t") -> { + subclassCode = line.substring(1, 3).toInt(16) + subclassCodes.add(SubclassCode(classCode, subclassCode, line.substring(5))) + // class line + } + line.startsWith("C ") -> { + classCode = line.substring(2, 4).toInt(16) + classCodes.add(ClassCode(classCode, line.substring(6))) + } + else -> { + error("Invalid raw data") + } + } + line = reader.readLine() + } + } + } + } catch (e: IOException) { + throw RuntimeException(e) + } + } + + internal data class ClassCode(val classCode: Int, val name: String) + + internal data class SubclassCode(val classCode: Int, val subclassCode: Int, val name: String) + + internal data class ProtocolCode(val classCode: Int, val subclassCode: Int, val protocolCode: Int, val name: String) +} \ No newline at end of file diff --git a/examples/enumerate_native/README.md b/examples/enumerate_native/README.md new file mode 100644 index 00000000..f35b1095 --- /dev/null +++ b/examples/enumerate_native/README.md @@ -0,0 +1,47 @@ +# Device Enumeration (Native) + +This example project demonstrates how th build a native application that +enumerates connected devices using [GraalVM](https://www.graalvm.org/) and +this _Java Does USB_ library. + +## Build and Run + +### Prerequisites + +- [GraalVM](https://www.graalvm.org/) 25 or higher +- [Maven](https://maven.apache.org/) 3.9 or higher + + +### Preparation + +GraalVM needs help to learn about the Java FFM downcall and upcall descriptors, +and it needs some help to include all required methods. The relevant items +differ from operating system to operating system. When building the native image, +the operating system must be selected by changing the path in the file +`native-image.properties` in the directory +`src/main/resources/META-INF/native-image/net.codecrete.usb.examples/enumerate_native`. + +```properties +Args = --enable-native-access=ALL-UNNAMED -H:ConfigurationFileDirectories=config/macos +``` + +Note the last word of the line. In this case, it is `macos`. Change this to +`linux` or `windows` if needed. + +In your own Maven project, you might also need to move the file or rather rename +directory. It must be named according to the pattern +`src/main/resources/META-INF/native-image//`. + + +### Building + +```shell +mvn -Pnative package +``` + + +### Running + +```shell +./target/enumerate-native +``` diff --git a/examples/enumerate_native/config/linux/reachability-metadata.json b/examples/enumerate_native/config/linux/reachability-metadata.json new file mode 100644 index 00000000..e1746c04 --- /dev/null +++ b/examples/enumerate_native/config/linux/reachability-metadata.json @@ -0,0 +1,111 @@ +{ + "foreign": { + "downcalls": [ + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jlong", + "void*" + ], + "options": { + "captureCallState": true, + "firstVariadicArg": 2 + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + } + ] + } +} \ No newline at end of file diff --git a/examples/enumerate_native/config/macos/reachability-metadata.json b/examples/enumerate_native/config/macos/reachability-metadata.json new file mode 100644 index 00000000..113fb587 --- /dev/null +++ b/examples/enumerate_native/config/macos/reachability-metadata.json @@ -0,0 +1,318 @@ +{ + "foreign": { + "upcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ], + "downcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "struct(jlong,jlong)", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jdouble", + "jdouble", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jbyte", + "parameterTypes": [ + "void*", + "jlong", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)" + ] + }, + { + "returnType": "void", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "jint", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "void*" + ] + }, + { + "returnType": "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ] + }, + "reflection": [ + { + "type": "net.codecrete.usb.macos.gen.corefoundation.CFMessagePortCreateLocal$callout$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "java.lang.foreign.MemorySegment", + "java.lang.foreign.MemorySegment" + ] + } + ] + }, + { + "type": "net.codecrete.usb.macos.gen.iokit.IOServiceAddMatchingNotification$callback$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int" + ] + } + ] + } + ] +} diff --git a/examples/enumerate_native/config/windows/reachability-metadata.json b/examples/enumerate_native/config/windows/reachability-metadata.json new file mode 100644 index 00000000..f3abe566 --- /dev/null +++ b/examples/enumerate_native/config/windows/reachability-metadata.json @@ -0,0 +1,377 @@ +{ + "foreign": { + "downcalls": [ + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "void*", + "void*", + "jint", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jint", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jshort", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint", + "jint", + "jint", + "jint", + "jint", + "void*", + "void*", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "jlong", + "void*", + "jint", + "jint", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "jint", + "void*", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong", + "jint" + ], + "options": { + "captureCallState": true + } + } + ], + "upcalls": [ + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + } + ] + }, + "reflection": [ + { + "type": "windows.win32.ui.windowsandmessaging.WNDPROC$Function", + "methods": [ + { + "name": "invoke", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "long", + "long" + ] + } + ] + } + ] +} diff --git a/examples/enumerate_native/pom.xml b/examples/enumerate_native/pom.xml new file mode 100644 index 00000000..c6a9c555 --- /dev/null +++ b/examples/enumerate_native/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + + net.codecrete.usb.examples + enumerate_native + jar + 1.0-SNAPSHOT + enumerate_native + https://www.github.com/manuelbl/java-does-usb + + + 25 + 25 + UTF-8 + 0.11.0 + 1.3.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + true + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + net.codecrete.usb.examples.App + true + + + + + + + + + + net.codecrete.usb + java-does-usb + ${java-does-usb.version} + + + junit + junit + 3.8.1 + test + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + compile-no-fork + + package + + + + + + + + + diff --git a/examples/enumerate_native/src/main/java/net/codecrete/usb/examples/App.java b/examples/enumerate_native/src/main/java/net/codecrete/usb/examples/App.java new file mode 100644 index 00000000..943f20e3 --- /dev/null +++ b/examples/enumerate_native/src/main/java/net/codecrete/usb/examples/App.java @@ -0,0 +1,19 @@ +// +// Java Does USB +// Copyright (c) 2025 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.examples; + +import net.codecrete.usb.Usb; + +public class App +{ + public static void main(String[] args) { + for (var device : Usb.getDevices()) { + System.out.println(device); + } + } +} diff --git a/examples/enumerate_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/enumerate_native/native-image.properties b/examples/enumerate_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/enumerate_native/native-image.properties new file mode 100644 index 00000000..4e4f3471 --- /dev/null +++ b/examples/enumerate_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/enumerate_native/native-image.properties @@ -0,0 +1 @@ +Args = --enable-native-access=ALL-UNNAMED -H:ConfigurationFileDirectories=config/macos diff --git a/examples/epaper_display/.mvn/wrapper/maven-wrapper.properties b/examples/epaper_display/.mvn/wrapper/maven-wrapper.properties index 6d3a5665..f3283b08 100644 --- a/examples/epaper_display/.mvn/wrapper/maven-wrapper.properties +++ b/examples/epaper_display/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/examples/epaper_display/README.md b/examples/epaper_display/README.md index c9d3b628..c45f7e08 100644 --- a/examples/epaper_display/README.md +++ b/examples/epaper_display/README.md @@ -4,7 +4,7 @@ This sample shows how to communicate with an IT8951 controller for e-paper displ ## Prerequisites -- Java 21 +- Java 22 - Apache Maven - 64-bit operating system (macOS, Linux, Windows) - IT8951 controller @@ -17,9 +17,9 @@ be temporarily detached.) ## How to run -### Install Java 21 +### Install Java 22 or higher -Check that *Java 21* is installed: +Check that Java 22 or higher is installed: ```shell $ java -version @@ -45,24 +45,22 @@ $ mvn compile exec:exec [INFO] Scanning for projects... [INFO] [INFO] -------------< net.codecrete.usb.examples:epaper-display >-------------- -[INFO] Building epaper-display 0.5.1 -[INFO] from pom.xml +[INFO] Building epaper-display 1.3.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] -[INFO] --- resources:3.3.1:resources (default-resources) @ epaper-display --- -[INFO] skip non existing resourceDirectory /Users/me/Documents/JavaDoesUSB/examples/epaper_display/src/main/resources +[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ epaper-display --- +[INFO] skip non existing resourceDirectory /home/user/Documents/JavaDoesUSB/examples/epaper_display/src/main/resources [INFO] -[INFO] --- compiler:3.11.0:compile (default-compile) @ epaper-display --- -[INFO] Changes detected - recompiling the module! :source -[INFO] Compiling 2 source files with javac [debug release 20] to target/classes +[INFO] --- maven-compiler-plugin:3.12.1:compile (default-compile) @ epaper-display --- +[INFO] Nothing to compile - all classes are up to date. [INFO] -[INFO] --- exec:3.1.0:exec (default-cli) @ epaper-display --- +[INFO] --- exec-maven-plugin:3.1.1:exec (default-cli) @ epaper-display --- Display size: 1200 x 825 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ -[INFO] Total time: 1.502 s -[INFO] Finished at: 2023-07-02T14:08:50+02:00 +[INFO] Total time: 2.247 s +[INFO] Finished at: 2024-10-13T16:48:43+01:00 [INFO] ------------------------------------------------------------------------ ``` @@ -81,6 +79,6 @@ $ sudo -i Password: $ cd /Users/me/Documents/JavaDoesUSB/examples/epaper_display $ export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-20.jdk/Contents/Home -$ $JAVA_HOME/bin/java --enable-preview --enable-native-access=ALL-UNNAMED -cp target/classes:/Users/me/.m2/repository/net/codecrete/usb/java-does-usb/0.5.1/java-does-usb-0.5.1.jar net.codecrete.usb.examples.EPaperDisplay +$ $JAVA_HOME/bin/java --enable-native-access=ALL-UNNAMED -cp target/classes:/Users/me/.m2/repository/net/codecrete/usb/java-does-usb/1.3.0/java-does-usb-1.3.0.jar net.codecrete.usb.examples.EPaperDisplay Display size: 1200 x 825 ``` diff --git a/examples/epaper_display/mvnw.cmd b/examples/epaper_display/mvnw.cmd index c4586b56..f80fbad3 100644 --- a/examples/epaper_display/mvnw.cmd +++ b/examples/epaper_display/mvnw.cmd @@ -1,205 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/examples/epaper_display/pom.xml b/examples/epaper_display/pom.xml index 697fdc5f..b69b1432 100644 --- a/examples/epaper_display/pom.xml +++ b/examples/epaper_display/pom.xml @@ -6,32 +6,33 @@ net.codecrete.usb.examples epaper-display - 0.6.0-SNAPSHOT + 1.3.0 epaper-display https://github.com/manuelbl/JavaDoesUSB/examples/epaper_display UTF-8 - 21 - 21 + 22 + 22 + 1.3.0 net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + ${java-does-usb.version} - + maven-clean-plugin - 3.3.1 + 3.3.2 @@ -40,26 +41,23 @@ maven-compiler-plugin - 3.11.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 22 + 22 + 22 maven-surefire-plugin - 2.22.1 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED maven-jar-plugin - 3.1.2 + 3.3.0 maven-install-plugin @@ -76,16 +74,15 @@ maven-project-info-reports-plugin - 3.4.5 + 3.5.0 org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.1.1 - ${JAVA_HOME}/bin/java + java - --enable-preview --enable-native-access=ALL-UNNAMED -classpath diff --git a/examples/epaper_display/src/main/java/net/codecrete/usb/examples/IT8951Driver.java b/examples/epaper_display/src/main/java/net/codecrete/usb/examples/IT8951Driver.java index 7170fc71..47ae2b29 100644 --- a/examples/epaper_display/src/main/java/net/codecrete/usb/examples/IT8951Driver.java +++ b/examples/epaper_display/src/main/java/net/codecrete/usb/examples/IT8951Driver.java @@ -7,8 +7,8 @@ package net.codecrete.usb.examples; -import net.codecrete.usb.USB; -import net.codecrete.usb.USBDevice; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; @@ -35,7 +35,7 @@ public class IT8951Driver { (byte)0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x94, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - private USBDevice device; + private UsbDevice device; private int sequenceNo = 1; private DisplayInfo displayInfo; @@ -46,7 +46,7 @@ public class IT8951Driver { * @throws IllegalStateException if no IT8951 device is found */ public void open() { - var optionalDevice = USB.getDevice(0x048d, 0x8951); + var optionalDevice = Usb.findDevice(0x048d, 0x8951); if (optionalDevice.isEmpty()) throw new IllegalStateException("No IT8951 device found"); @@ -276,7 +276,7 @@ private Status readStatus() { if (result.length == 13) return Status.from(result); - throw new RuntimeException(String.format("Unexpected length of status block (%d)", result.length)); + throw new IllegalStateException(String.format("Unexpected length of status block (%d)", result.length)); } /** diff --git a/examples/monitor/.mvn/wrapper/maven-wrapper.properties b/examples/monitor/.mvn/wrapper/maven-wrapper.properties index 6d3a5665..f3283b08 100644 --- a/examples/monitor/.mvn/wrapper/maven-wrapper.properties +++ b/examples/monitor/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/examples/monitor/README.md b/examples/monitor/README.md index 6c1c892b..f32c60c9 100644 --- a/examples/monitor/README.md +++ b/examples/monitor/README.md @@ -4,15 +4,15 @@ This sample program monitors USB devices as they are connected and disconnected. ## Prerequisites -- Java 20 +- Java 22 - Apache Maven - 64-bit operating system (Windows, macOS, Linux) ## How to run -### Install Java 20 +### Install Java 22 or higher -Check that *Java 20* is installed: +Check that Java 22 or higher is installed: ```shell $ java -version @@ -35,22 +35,30 @@ If it is not present, install it, typically using package manager like *Homebrew ```shell $ cd JavaDoesUSB/examples/monitor $ mvn compile exec:exec + [INFO] Scanning for projects... [INFO] [INFO] -----------------< net.codecrete.usb.examples:monitor >----------------- -[INFO] Building monitor 0.5.1 +[INFO] Building monitor 1.3.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] -[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ monitor --- -[INFO] Using 'UTF-8' encoding to copy filtered resources. -[INFO] skip non existing resourceDirectory /Users/me/Documents/JavaDoesUSB/examples/monitor/src/main/resources +[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ monitor --- +[INFO] Copying 1 resource from src/main/resources to target/classes [INFO] -[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ monitor --- -[INFO] Changes detected - recompiling the module! -[INFO] Compiling 1 source file to /Users/me/Documents/JavaDoesUSB/examples/monitor/target/classes +[INFO] --- maven-compiler-plugin:3.12.1:compile (default-compile) @ monitor --- +[INFO] Nothing to compile - all classes are up to date. [INFO] -[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ monitor --- -Present: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 8D8F515C5456, ID: 4295291950 -Present: VID: 0x1a40, PID: 0x0801, manufacturer: null, product: USB 2.0 Hub, serial: null, ID: 4295291734 +[INFO] --- exec-maven-plugin:3.1.1:exec (default-cli) @ monitor --- +Present: VID: 0x1d6b, PID: 0x0002, manufacturer: Linux 6.5.0-18-generic xhci-hcd, product: xHCI Host Controller, serial: 0000:00:14.0, ID: /dev/bus/usb/001/001 +Present: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/005 Monitoring... Press ENTER to quit. +Disconnected: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/005 +Connected: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/009 + +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 17.647 s +[INFO] Finished at: 2024-10-13T16:50:59+01:00 +[INFO] ----------------------------------------------------------------------- ``` diff --git a/examples/monitor/mvnw.cmd b/examples/monitor/mvnw.cmd index c4586b56..f80fbad3 100644 --- a/examples/monitor/mvnw.cmd +++ b/examples/monitor/mvnw.cmd @@ -1,205 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/examples/monitor/pom.xml b/examples/monitor/pom.xml index d94ef9a3..52206a11 100644 --- a/examples/monitor/pom.xml +++ b/examples/monitor/pom.xml @@ -6,22 +6,23 @@ net.codecrete.usb.examples monitor - 0.6.0-SNAPSHOT + 1.3.0 monitor https://github.com/manuelbl/JavaDoesUSB/examples/monitor UTF-8 - 21 - 21 + 22 + 22 + 1.3.0 net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + ${java-does-usb.version} org.tinylog @@ -41,66 +42,62 @@ - + maven-clean-plugin - 3.1.0 + 3.3.2 maven-resources-plugin - 3.0.2 + 3.3.1 maven-compiler-plugin - 3.8.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 22 + 22 + 22 maven-surefire-plugin - 2.22.1 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED maven-jar-plugin - 3.0.2 + 3.3.0 maven-install-plugin - 2.5.2 + 3.1.1 maven-deploy-plugin - 2.8.2 + 3.1.1 maven-site-plugin - 3.7.1 + 3.12.1 maven-project-info-reports-plugin - 3.0.0 + 3.5.0 org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.1.1 java - --enable-preview --enable-native-access=ALL-UNNAMED -classpath diff --git a/examples/monitor/src/main/java/net/codecrete/usb/examples/Monitor.java b/examples/monitor/src/main/java/net/codecrete/usb/examples/Monitor.java index a897ba94..482d1b9f 100644 --- a/examples/monitor/src/main/java/net/codecrete/usb/examples/Monitor.java +++ b/examples/monitor/src/main/java/net/codecrete/usb/examples/Monitor.java @@ -7,8 +7,8 @@ package net.codecrete.usb.examples; -import net.codecrete.usb.USB; -import net.codecrete.usb.USBDevice; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; import java.io.IOException; @@ -19,11 +19,11 @@ public class Monitor { public static void main(String[] args) throws IOException { // register callbacks for events - USB.setOnDeviceConnected((device) -> printDetails(device, "Connected")); - USB.setOnDeviceDisconnected((device) -> printDetails(device, "Disconnected")); + Usb.setOnDeviceConnected(device -> printDetails(device, "Connected")); + Usb.setOnDeviceDisconnected(device -> printDetails(device, "Disconnected")); // display the already present USB devices - for (var device : USB.getAllDevices()) + for (var device : Usb.getDevices()) printDetails(device, "Present"); // wait for ENTER to quit program @@ -31,7 +31,7 @@ public static void main(String[] args) throws IOException { System.in.read(); } - private static void printDetails(USBDevice device, String event) { + private static void printDetails(UsbDevice device, String event) { System.out.printf("%-14s", event + ":"); System.out.println(device.toString()); } diff --git a/examples/monitor_kotlin/.gitignore b/examples/monitor_kotlin/.gitignore new file mode 100644 index 00000000..5ff6309b --- /dev/null +++ b/examples/monitor_kotlin/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/examples/monitor_kotlin/.mvn/wrapper/maven-wrapper.properties b/examples/monitor_kotlin/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..c595b009 --- /dev/null +++ b/examples/monitor_kotlin/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.14/apache-maven-3.9.14-bin.zip diff --git a/examples/monitor_kotlin/README.md b/examples/monitor_kotlin/README.md new file mode 100644 index 00000000..f98849da --- /dev/null +++ b/examples/monitor_kotlin/README.md @@ -0,0 +1,49 @@ +# USB Device Monitoring (Kotlin) + +This sample enumerates the connected USB devices and provides information about the interfaces and endpoints. + +## Prerequisites + +- Java 25 +- Apache Maven +- 64-bit operating system (Windows, macOS, Linux) + +## How to run + +### Install Java 25 or higher + +Check that Java 25 or higher is installed: + +```shell +$ java -version +``` + +If not, download and install it, e.g. from [Azul](https://www.azul.com/downloads/?package=jdk). + +### Install Maven + +Check that *Maven* is installed: + +```shell +$ mvn -version +``` + +If it is not present, install it, typically using package manager like *Homebrew* on macOS, *Chocolately* on Windows and *apt* on Linux. + +### Build a self-contained jar file + +```shell +$ cd JavaDoesUSB/examples/monitor_kotlin +$ mvn clean package +``` + +### Run the jar + +```shell +$ java --enable-native-access=ALL-UNNAMED -jar target/monitor-1.3.0-jar-with-dependencies.jar +Present: VID: 0x1d6b, PID: 0x0002, manufacturer: Linux 6.5.0-18-generic xhci-hcd, product: xHCI Host Controller, serial: 0000:00:14.0, ID: /dev/bus/usb/001/001 +Present: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/009 +Monitoring... Press ENTER to quit. +Disconnected: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/009 +Connected: VID: 0xcafe, PID: 0xceaf, manufacturer: JavaDoesUSB, product: Loopback, serial: 35A737883336, ID: /dev/bus/usb/001/010 +``` diff --git a/examples/monitor_kotlin/mvnw b/examples/monitor_kotlin/mvnw new file mode 100755 index 00000000..bd8896bf --- /dev/null +++ b/examples/monitor_kotlin/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/examples/monitor_kotlin/mvnw.cmd b/examples/monitor_kotlin/mvnw.cmd new file mode 100644 index 00000000..5761d948 --- /dev/null +++ b/examples/monitor_kotlin/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/examples/monitor_kotlin/pom.xml b/examples/monitor_kotlin/pom.xml new file mode 100644 index 00000000..2612f221 --- /dev/null +++ b/examples/monitor_kotlin/pom.xml @@ -0,0 +1,92 @@ + + 4.0.0 + + net.codecrete.usb.examples + monitor + 1.3.0 + jar + + monitor + https://github.com/manuelbl/JavaDoesUSB/examples/monitor_kotlin + + + 2.3.21 + true + UTF-8 + net.codecrete.usb.examples.MonitorKt + 1.3.0 + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + true + + + org.apache.maven.plugins + maven-assembly-plugin + 3.6.0 + + + make-assembly + package + + single + + + + + ${main.class} + + + + jar-with-dependencies + + + + + + + + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + net.codecrete.usb + java-does-usb + ${java-does-usb.version} + + + org.tinylog + tinylog-api + 2.7.0 + + + org.tinylog + tinylog-impl + 2.7.0 + + + org.tinylog + jsl-tinylog + 2.7.0 + + + junit + junit + 4.13.2 + test + + + diff --git a/examples/monitor_kotlin/src/main/kotlin/net/codecrete/usb/examples/Monitor.kt b/examples/monitor_kotlin/src/main/kotlin/net/codecrete/usb/examples/Monitor.kt new file mode 100644 index 00000000..b16d568a --- /dev/null +++ b/examples/monitor_kotlin/src/main/kotlin/net/codecrete/usb/examples/Monitor.kt @@ -0,0 +1,41 @@ +// +// Java Does USB +// Copyright (c) 2023 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// +package net.codecrete.usb.examples + +import net.codecrete.usb.Usb +import net.codecrete.usb.UsbDevice + +/** + * Sample application monitoring USB devices as they are connected and disconnected. + */ + +fun main() { + Monitor().monitor() +} + +class Monitor { + fun monitor() { + // register callbacks for events + Usb.setOnDeviceConnected { device -> printDetails(device, "Connected") } + Usb.setOnDeviceDisconnected { device -> + printDetails( device, "Disconnected") + } + + // display the already present USB devices + for (device in Usb.getDevices()) + printDetails(device, "Present") + + // wait for ENTER to quit program + println("Monitoring... Press ENTER to quit.") + System.`in`.read() + } + + private fun printDetails(device: UsbDevice, event: String) { + print(String.format("%-14s", "$event:")) + println(device.toString()) + } +} \ No newline at end of file diff --git a/examples/monitor_native/README.md b/examples/monitor_native/README.md new file mode 100644 index 00000000..3018321d --- /dev/null +++ b/examples/monitor_native/README.md @@ -0,0 +1,49 @@ +# Device Monitoring (Native) + +This example project demonstrates how to build a native application that +monitors USB devices using [GraalVM](https://www.graalvm.org/) and +this _Java Does USB_ library. + +## Build and Run + +### Prerequisites + +- [GraalVM](https://www.graalvm.org/) 25 or higher +- [Maven](https://maven.apache.org/) 3.9 or higher + + +### Preparation + +GraalVM needs help to learn about the Java FFM downcall and upcall descriptors, +and it needs some help to include all required methods. The relevant items +differ from operating system to operating system. When building the native image, +the operating system must be selected by changing the path in the file +`native-image.properties` in the directory +`src/main/resources/META-INF/native-image/net.codecrete.usb.examples/monitor_native`. + +```properties +Args = --enable-native-access=ALL-UNNAMED -H:ConfigurationFileDirectories=config/macos +``` + +Note the last word of the line. In this case, it is `macos`. Change this to +`linux` or `windows` if needed. + +In your own Maven project, you might also need to move the file or rather rename +directory. It must be named according to the pattern +`src/main/resources/META-INF/native-image//`. + +Also check that the environment variable `JAVA_HOME` points to the GraalVM directory. + + +### Building + +```shell +mvn -Pnative package +``` + + +### Running + +```shell +./target/monitor-native +``` diff --git a/examples/monitor_native/config/linux/reachability-metadata.json b/examples/monitor_native/config/linux/reachability-metadata.json new file mode 100644 index 00000000..e1746c04 --- /dev/null +++ b/examples/monitor_native/config/linux/reachability-metadata.json @@ -0,0 +1,111 @@ +{ + "foreign": { + "downcalls": [ + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jlong", + "void*" + ], + "options": { + "captureCallState": true, + "firstVariadicArg": 2 + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + } + ] + } +} \ No newline at end of file diff --git a/examples/monitor_native/config/macos/reachability-metadata.json b/examples/monitor_native/config/macos/reachability-metadata.json new file mode 100644 index 00000000..113fb587 --- /dev/null +++ b/examples/monitor_native/config/macos/reachability-metadata.json @@ -0,0 +1,318 @@ +{ + "foreign": { + "upcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ], + "downcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "struct(jlong,jlong)", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jdouble", + "jdouble", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jbyte", + "parameterTypes": [ + "void*", + "jlong", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)" + ] + }, + { + "returnType": "void", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "jint", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "void*" + ] + }, + { + "returnType": "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ] + }, + "reflection": [ + { + "type": "net.codecrete.usb.macos.gen.corefoundation.CFMessagePortCreateLocal$callout$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "java.lang.foreign.MemorySegment", + "java.lang.foreign.MemorySegment" + ] + } + ] + }, + { + "type": "net.codecrete.usb.macos.gen.iokit.IOServiceAddMatchingNotification$callback$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int" + ] + } + ] + } + ] +} diff --git a/examples/monitor_native/config/windows/reachability-metadata.json b/examples/monitor_native/config/windows/reachability-metadata.json new file mode 100644 index 00000000..f3abe566 --- /dev/null +++ b/examples/monitor_native/config/windows/reachability-metadata.json @@ -0,0 +1,377 @@ +{ + "foreign": { + "downcalls": [ + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "void*", + "void*", + "jint", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jint", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jshort", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint", + "jint", + "jint", + "jint", + "jint", + "void*", + "void*", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "jlong", + "void*", + "jint", + "jint", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "jint", + "void*", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong", + "jint" + ], + "options": { + "captureCallState": true + } + } + ], + "upcalls": [ + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + } + ] + }, + "reflection": [ + { + "type": "windows.win32.ui.windowsandmessaging.WNDPROC$Function", + "methods": [ + { + "name": "invoke", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "long", + "long" + ] + } + ] + } + ] +} diff --git a/examples/monitor_native/pom.xml b/examples/monitor_native/pom.xml new file mode 100644 index 00000000..68e930de --- /dev/null +++ b/examples/monitor_native/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + + net.codecrete.usb.examples + monitor_native + jar + 1.0-SNAPSHOT + monitor_native + https://www.github.com/manuelbl/java-does-usb + + + 25 + 25 + UTF-8 + 0.11.0 + 1.3.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + true + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + net.codecrete.usb.examples.App + true + + + + + + + + + + net.codecrete.usb + java-does-usb + ${java-does-usb.version} + + + junit + junit + 3.8.1 + test + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + compile-no-fork + + package + + + + + + + + + diff --git a/examples/monitor_native/src/main/java/net/codecrete/usb/examples/App.java b/examples/monitor_native/src/main/java/net/codecrete/usb/examples/App.java new file mode 100644 index 00000000..3bb1ccb9 --- /dev/null +++ b/examples/monitor_native/src/main/java/net/codecrete/usb/examples/App.java @@ -0,0 +1,38 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.examples; + +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; + +import java.io.IOException; + +/** + * Sample application monitoring USB devices as they are connected and disconnected. + */ +public class App { + + static void main() throws IOException { + // register callbacks for events + Usb.setOnDeviceConnected(device -> printDetails(device, "Connected")); + Usb.setOnDeviceDisconnected(device -> printDetails(device, "Disconnected")); + + // display the already present USB devices + for (var device : Usb.getDevices()) + printDetails(device, "Present"); + + // wait for ENTER to quit program + System.out.println("Monitoring... Press ENTER to quit."); + System.in.read(); + } + + private static void printDetails(UsbDevice device, String event) { + System.out.printf("%-14s", event + ":"); + System.out.println(device.toString()); + } +} \ No newline at end of file diff --git a/examples/monitor_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/monitor_native/native-image.properties b/examples/monitor_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/monitor_native/native-image.properties new file mode 100644 index 00000000..cf6e3f9a --- /dev/null +++ b/examples/monitor_native/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/monitor_native/native-image.properties @@ -0,0 +1 @@ +Args = --enable-native-access=ALL-UNNAMED -H:ConfigurationFileDirectories=config/windows diff --git a/examples/stm_dfu/.mvn/wrapper/maven-wrapper.properties b/examples/stm_dfu/.mvn/wrapper/maven-wrapper.properties index 6d3a5665..f3283b08 100644 --- a/examples/stm_dfu/.mvn/wrapper/maven-wrapper.properties +++ b/examples/stm_dfu/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/examples/stm_dfu/README.md b/examples/stm_dfu/README.md index f2a6d308..8c5285d0 100644 --- a/examples/stm_dfu/README.md +++ b/examples/stm_dfu/README.md @@ -6,15 +6,15 @@ Even though the DFU ## Prerequisites -- Java 20 +- Java 22 - Apache Maven - 64-bit operating system (Windows, macOS, Linux) ## How to run -### Install Java 20 +### Install Java 22 or higher -Check that *Java 20* is installed: +Check that Java 22 or higher is installed: ```shell $ java -version @@ -58,7 +58,7 @@ Run the command below (adapting the file path depending on your specific board): ```shell $ mvn package -$ java --enable-preview --enable-native-access=ALL-UNNAMED -jar target/stm_dfu-0.5.1.jar ../../test-devices/loopback-stm32/bin/blackpill-f401cc.bin +$ java --enable-native-access=ALL-UNNAMED -jar target/stm_dfu-1.3.0.jar ../../test-devices/loopback-stm32/bin/blackpill-f401cc.bin DFU device found with serial 35A737883336. Target memory segment: Internal Flash Erasing page at 0x8000000 (size 0x4000) diff --git a/examples/stm_dfu/mvnw.cmd b/examples/stm_dfu/mvnw.cmd index c4586b56..f80fbad3 100644 --- a/examples/stm_dfu/mvnw.cmd +++ b/examples/stm_dfu/mvnw.cmd @@ -1,205 +1,205 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/examples/stm_dfu/pom.xml b/examples/stm_dfu/pom.xml index 5dcbc1de..0e3aa46d 100644 --- a/examples/stm_dfu/pom.xml +++ b/examples/stm_dfu/pom.xml @@ -4,61 +4,61 @@ net.codecrete.usb.examples stm_dfu - 0.6.0-SNAPSHOT + 1.3.0 stm_dfu https://github.com/manuelbl/JavaDoesUSB/examples/stm_dfu UTF-8 - 21 - 21 + 22 + 22 + 1.3.0 net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + ${java-does-usb.version} + maven-clean-plugin - 3.1.0 + 3.3.2 + maven-resources-plugin - 3.0.2 + 3.3.1 maven-compiler-plugin - 3.8.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 22 + 22 + 22 maven-jar-plugin - 3.0.2 + 3.3.0 maven-surefire-plugin - 2.22.2 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED maven-shade-plugin - 3.3.0 + 3.5.1 package diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFU.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFU.java index 0c785461..4ca4d2a3 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFU.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFU.java @@ -12,7 +12,7 @@ import java.nio.file.Path; /** - * Command line application for upload firmware to STM32. + * Command line application for uploading firmware to STM32 microcontrollers. *

* Only the STM32 variant of the DFU protocol is supported. * Only binary firmware format is supported (no .hex or .dfu files). @@ -53,8 +53,8 @@ public static void main(String[] args) { System.exit(4); return; } - var device = devices.get(0); - System.out.printf("DFU device found with serial %s.%n", device.serialNumber()); + var device = devices.getFirst(); + System.out.printf("DFU device found with serial %s.%n", device.getSerialNumber()); // download and verify firmware try { @@ -64,7 +64,8 @@ public static void main(String[] args) { System.out.println("Firmware successfully downloaded and verified"); device.startApplication(); - System.out.println("DFU mode exited and firmware started"); + device.waitForDisconnect(); + System.out.println("DFU mode ended and firmware started"); device.close(); diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUDevice.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUDevice.java index f5b12f88..4678e066 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUDevice.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUDevice.java @@ -11,7 +11,9 @@ import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; + +import static net.codecrete.usb.UsbRecipient.INTERFACE; +import static net.codecrete.usb.UsbRequestType.CLASS; /** * DFU device. @@ -21,22 +23,22 @@ */ public class DFUDevice { - private final USBDevice usbDevice_; - private final int interfaceNumber_; - private final int transferSize_; - private final Version dfuVersion_; + private final UsbDevice usbDevice; + private final int interfaceNumber; + private final int transferSize; + private final Version dfuVersion; - private List segments_; + private List segments; /** * Gets all connected DFU devices * @return List of DFU devices */ public static List getAll() { - return USB.getAllDevices().stream() - .filter(DFUDevice::hasDFUDescriptor) + return Usb.findDevices(DFUDevice::hasDFUDescriptor) + .stream() .map(DFUDevice::new) - .collect(Collectors.toList()); + .toList(); } /** @@ -44,8 +46,8 @@ public static List getAll() { * @param device USB device * @return {@code true} if it has a DFU descriptor, {@code false} otherwise */ - public static boolean hasDFUDescriptor(USBDevice device) { - return getDFUDescriptorOffset(device.configurationDescriptor()) > 0 + public static boolean hasDFUDescriptor(UsbDevice device) { + return getDFUDescriptorOffset(device.getConfigurationDescriptor()) > 0 && getDFUInterfaceNumber(device) >= 0; } @@ -69,11 +71,11 @@ public static int getDFUDescriptorOffset(byte[] descriptor) { * @param device the USB device * @return the interface number, of -1 if not found */ - public static int getDFUInterfaceNumber(USBDevice device) { - for (var intf : device.interfaces()) { - var alt = intf.alternate(); - if (alt.classCode() == 0xFE && alt.subclassCode() == 0x01 && alt.protocolCode() == 0x02) - return intf.number(); + public static int getDFUInterfaceNumber(UsbDevice device) { + for (var intf : device.getInterfaces()) { + var alt = intf.getCurrentAlternate(); + if (alt.getClassCode() == 0xFE && alt.getSubclassCode() == 0x01 && alt.getProtocolCode() == 0x02) + return intf.getNumber(); } return -1; @@ -86,41 +88,41 @@ public static int getDFUInterfaceNumber(USBDevice device) { *

* @param usbDevice the USB device */ - public DFUDevice(USBDevice usbDevice) { - usbDevice_ = usbDevice; - interfaceNumber_ = getDFUInterfaceNumber(usbDevice); + public DFUDevice(UsbDevice usbDevice) { + this.usbDevice = usbDevice; + interfaceNumber = getDFUInterfaceNumber(usbDevice); - var configDesc = usbDevice.configurationDescriptor(); + var configDesc = usbDevice.getConfigurationDescriptor(); int offset = getDFUDescriptorOffset(configDesc); assert offset > 0; - transferSize_ = getInt16(configDesc, offset + 5); - dfuVersion_ = new Version(getInt16(configDesc, offset + 7)); + transferSize = getInt16(configDesc, offset + 5); + dfuVersion = new Version(getInt16(configDesc, offset + 7)); } /** * Gets the DFU protocol version. * @return the protocol version */ - public Version dfuVersion() { - return dfuVersion_; + public Version getDfuVersion() { + return dfuVersion; } /** * Gets the device serial number. * @return the serial number */ - public String serialNumber() { - return usbDevice_.serialNumber(); + public String getSerialNumber() { + return usbDevice.getSerialNumber(); } /** * Opens the DFU device for communication. */ public void open() { - usbDevice_.open(); - usbDevice_.claimInterface(interfaceNumber_); - segments_ = Segment.getSegments(usbDevice_, interfaceNumber_); + usbDevice.open(); + usbDevice.claimInterface(interfaceNumber); + segments = Segment.getSegments(usbDevice, interfaceNumber); clearErrorIfNeeded(); } @@ -128,23 +130,44 @@ public void open() { * Closes the DFU device. */ public void close() { - usbDevice_.close(); + usbDevice.close(); + } + + /** + * Waits until the device disconnects. + *

+ * Disconnection is a side effect of leaving DFU mode. + *

+ *

+ * If the device does not disconnect after 5 seconds, + * an exception will be thrown. + *

+ */ + public void waitForDisconnect() { + var waitingTime = 5000; + while (waitingTime > 0 && usbDevice.isConnected()) { + sleep(100); + waitingTime -= 100; + } + + if (usbDevice.isConnected()) + throw new DFUException("Device did not restart (try disconnecting and reconnecting it)"); } /** * Clears an error status. */ public void clearStatus() { - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.CLEAR_STATUS.value(), 0, interfaceNumber_); - usbDevice_.controlTransferOut(setup, null); + var transfer = createDfuControlTransfer(DFURequest.CLEAR_STATUS, 0); + usbDevice.controlTransferOut(transfer, null); } /** * Aborts the download mode. */ public void abort() { - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.ABORT.value(), 0, interfaceNumber_); - usbDevice_.controlTransferOut(setup, null); + var transfer = createDfuControlTransfer(DFURequest.ABORT, 0); + usbDevice.controlTransferOut(transfer, null); } /** @@ -152,8 +175,11 @@ public void abort() { * @return the status */ public DFUStatus getStatus() { - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.GET_STATUS.value(), 0, interfaceNumber_); - return DFUStatus.fromBytes(usbDevice_.controlTransferIn(setup, 6)); + var transfer = createDfuControlTransfer(DFURequest.GET_STATUS, 0); + var response = usbDevice.controlTransferIn(transfer, 6); + if (response.length != 6) + throw new DFUException("Invalid response from GET_STATUS request"); + return DFUStatus.fromBytes(response); } /** @@ -165,8 +191,7 @@ public DFUStatus getStatus() { public byte[] read(int address, int length) { expectState(DeviceState.DFU_IDLE, DeviceState.DFU_DNLOAD_IDLE); setAddress(address); - exitDownloadMode(); - + exitMode(); expectState(DeviceState.DFU_IDLE, DeviceState.DFU_UPLOAD_IDLE); var result = new byte[length]; @@ -175,17 +200,15 @@ public byte[] read(int address, int length) { int offset = 0; int blockNum = 2; while (offset < length) { - int chunkSize = Math.min(transferSize_, length - offset); - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.UPLOAD.value(), blockNum, interfaceNumber_); - var chunk = usbDevice_.controlTransferIn(setup, chunkSize); + int chunkSize = Math.min(transferSize, length - offset); + var transfer = createDfuControlTransfer(DFURequest.UPLOAD, blockNum); + var chunk = usbDevice.controlTransferIn(transfer, chunkSize); System.arraycopy(chunk, 0, result, offset, chunkSize); offset += chunkSize; blockNum += 1; } - // request zero lenght chunk to exit out of upload mode - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.UPLOAD.value(), blockNum, interfaceNumber_); - usbDevice_.controlTransferIn(setup, 0); + exitMode(); return result; } @@ -199,13 +222,13 @@ public void verify(byte[] firmware) { public void download(byte[] firmware) { int length = firmware.length; - // validate start and end address exist and are writable + // validate that start and end address exist and are writable int startAddress = STM32.FLASH_BASE_ADDRESS; var firstPage = getWritablePage(startAddress); getWritablePage(startAddress + length); - usbDevice_.selectAlternateSetting(interfaceNumber_, firstPage.segment().altSetting()); - System.out.printf("Target memory segment: %s%n", firstPage.segment().name()); + usbDevice.selectAlternateSetting(interfaceNumber, firstPage.segment().getAltSetting()); + System.out.printf("Target memory segment: %s%n", firstPage.segment().getName()); // erase if needed if (firstPage.isErasable()) @@ -217,14 +240,14 @@ public void download(byte[] firmware) { int offset = 0; int transaction = 2; while (offset < length) { - int chunkSize = Math.min(length - offset, transferSize_); + int chunkSize = Math.min(length - offset, transferSize); byte[] chunk = new byte[chunkSize]; System.arraycopy(firmware, offset, chunk, 0, chunkSize); System.out.printf("Writing data at 0x%x (size 0x%x)%n", startAddress + offset, chunkSize); - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.DOWNLOAD.value(), transaction, interfaceNumber_); - usbDevice_.controlTransferOut(setup, chunk); + var transfer = createDfuControlTransfer(DFURequest.DOWNLOAD, transaction); + usbDevice.controlTransferOut(transfer, chunk); finishDownloadCommand("writing data"); @@ -232,7 +255,7 @@ public void download(byte[] firmware) { transaction += 1; } - exitDownloadMode(); + exitMode(); } /** @@ -241,7 +264,7 @@ public void download(byte[] firmware) { * Only applicable to erasable sector, i.e. flash memory. *

*

- * Only entire pages can be erase. If start and end address to not fall onto + * Only entire pages can be erased. If start and end address to not fall onto * page boundaries, this method will extend the range to be erased. *

* @param startAddress the start address of the range @@ -259,20 +282,20 @@ public void erase(int startAddress, int length) { System.out.printf("Erasing page at 0x%x (size 0x%x)%n", page.startAddress(), page.pageSize()); erasePage(page.startAddress()); - startAddress = page.endAddress(); + startAddress = page.getEndAddress(); } } public void erasePage(int address) { - execDownloadCommandWithAddress((byte) 0x41, "erasing page", address); + executeSpecialCommand((byte) 0x41, "erasing page", address); } public void setAddress(int address) { - execDownloadCommandWithAddress((byte) 0x21, "setting address", address); + executeSpecialCommand((byte) 0x21, "setting address", address); } - private void execDownloadCommandWithAddress(byte command, String action, int address) { - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.DOWNLOAD.value(), 0, interfaceNumber_); + private void executeSpecialCommand(byte command, String action, int address) { + var transfer = createDfuControlTransfer(DFURequest.DOWNLOAD, 0); var data = new byte[] { command, (byte) address, @@ -280,7 +303,7 @@ private void execDownloadCommandWithAddress(byte command, String action, int add (byte) (address >> 16), (byte) (address >> 24) }; - usbDevice_.controlTransferOut(setup, data); + usbDevice.controlTransferOut(transfer, data); finishDownloadCommand(action); } @@ -309,10 +332,10 @@ private Page getWritablePage(int address) { } private Page findPage(int address) { - return Segment.findPage(segments_, address); + return Segment.findPage(segments, address); } - private void exitDownloadMode() { + private void exitMode() { abort(); var status = getStatus(); @@ -325,8 +348,10 @@ private void exitDownloadMode() { public void startApplication() { expectState(DeviceState.DFU_IDLE, DeviceState.DFU_DNLOAD_IDLE); - var setup = new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, DFURequest.DOWNLOAD.value(), 2, interfaceNumber_); - usbDevice_.controlTransferOut(setup, null); + // By sending a zero-length download packet and querying the status, + // the device will leave DFU mode and restart. + var transfer = createDfuControlTransfer(DFURequest.DOWNLOAD, 0); + usbDevice.controlTransferOut(transfer, null); var status = getStatus(); if (status.state() != DeviceState.DFU_MANIFEST) @@ -359,7 +384,13 @@ private static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new DFUException("Sleep failed", e); } } + + private UsbControlTransfer createDfuControlTransfer(DFURequest request, int value) { + return new UsbControlTransfer(CLASS, INTERFACE, request.ordinal(), value, interfaceNumber); + } + } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFURequest.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFURequest.java index 00607e37..c927e105 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFURequest.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFURequest.java @@ -10,19 +10,47 @@ /** * DFU request. *

- * See USB Device Class Specification for Device Firmware Upgrade, version 1.1. + * See ST Microelectronics, application note AN3156. *

*/ public enum DFURequest { + /** + * Requests the device to leave DFU mode and enter the application. + *

+ * The Detach request is not meaningful in the case of the bootloader. The bootloader starts + * with a system reset depending on the boot mode configuration settings, which means that + * no other application is running at that time. + *

+ */ DETACH, + /** + * Requests data transfer from Host to the device in order to load them + * into device internal flash memory. Includes also erase commands. + */ DOWNLOAD, + /** + * Requests data transfer from device to Host in order to load content + * of device internal flash memory into a Host file. + */ UPLOAD, + /** + * Requests device to send status report to the Host (including status + * resulting from the last request execution and the state the device + * enters immediately after this request). + */ GET_STATUS, + /** + * Requests device to clear error status and move to next step. + */ CLEAR_STATUS, + /** + * Requests the device to send only the state it enters immediately + * after this request. + */ GET_STATE, - ABORT; - - public int value() { - return ordinal(); - } + /** + * Requests device to exit the current state/operation and enter idle + * state immediately + */ + ABORT } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUStatus.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUStatus.java index 4cd6e967..d6b44b00 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUStatus.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DFUStatus.java @@ -13,13 +13,12 @@ * See USB Device Class Specification for Device Firmware Upgrade, version 1.1. *

*/ -public record DFUStatus(DeviceStatus status, int pollTimeout, DeviceState state, int iString) { +public record DFUStatus(DeviceStatus status, int pollTimeout, DeviceState state) { public static DFUStatus fromBytes(byte[] data) { var status = DeviceStatus.fromValue(data[0]); var pollTimeout = (data[1] & 0xff) + 256 * (data[2] & 0xff) + 256 * 256 * (data[3] & 0xff); var state = DeviceState.fromValue(data[4]); - var iString = data[5] & 0x55; - return new DFUStatus(status, pollTimeout, state, iString); + return new DFUStatus(status, pollTimeout, state); } } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceState.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceState.java index 759da304..35532fd9 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceState.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceState.java @@ -14,31 +14,58 @@ *

*/ public enum DeviceState { - APP_IDLE, // Device is running its normal application. - APP_DETACH, // Device is running its normal application, has received the DFU_DETACH request, - // and is waiting for a USB reset. - DFU_IDLE, // Device is operating in the DFU mode and is waiting for requests. - DFU_DNLOAD_SYNC, // Device has received a block and is waiting for the host to solicit the status via DFU_GETSTATUS. - DFU_DNBUSY, // Device is programming a control-write block into its nonvolatile memories. - DFU_DNLOAD_IDLE, // Device is processing a download operation. Expecting DFU_DNLOAD requests. - DFU_MANIFEST_SYNC, // Device has received the final block of firmware from the host and is waiting for receipt of - // DFU_GETSTATUS to begin the Manifestation phase; or device has completed the Manifestation phase and is - // waiting for receipt of DFU_GETSTATUS. (Devices that can enter this state after the Manifestation phase - // set bmAttributes bit bitManifestationTolerant to 1.) - DFU_MANIFEST, // Device is in the Manifestation phase. (Not all devices will be able to respond to DFU_GETSTATUS - // when in this state.) - DFU_MANIFEST_WAIT_RESET, // Device has programmed its memories and is waiting for a USB reset or a power on reset. - // (Devices that must enter this state clear bitManifestationTolerant to 0.) - DFU_UPLOAD_IDLE, // The device is processing an upload operation. Expecting DFU_UPLOAD requests. - DFU_ERROR; // An error has occurred. Awaiting the DFU_CLRSTATUS request. - - public byte value() { - return (byte) ordinal(); - } - - private static final DeviceState[] values = values(); + /** + * Device is running its normal application. + */ + APP_IDLE, + /** + * Device is running its normal application, has received the DFU_DETACH request, + * and is waiting for a USB reset. + */ + APP_DETACH, + /** + * Device is operating in the DFU mode and is waiting for requests. + */ + DFU_IDLE, + /** + * Device has received a block and is waiting for the host to solicit the status via DFU_GETSTATUS. + */ + DFU_DNLOAD_SYNC, + /** + * Device is programming a control-write block into its nonvolatile memories. + */ + DFU_DNBUSY, + /** + * Device is processing a download operation. Expecting DFU_DNLOAD requests. + */ + DFU_DNLOAD_IDLE, + /** + * Device has received the final block of firmware from the host and is waiting for receipt of + * DFU_GETSTATUS to begin the Manifestation phase; or device has completed the Manifestation phase and is + * waiting for receipt of DFU_GETSTATUS. (Devices that can enter this state after the Manifestation phase + * set bmAttributes bit bitManifestationTolerant to 1.) + */ + DFU_MANIFEST_SYNC, + /** + * Device is in the Manifestation phase. (Not all devices will be able to respond to DFU_GETSTATUS + * when in this state. + */ + DFU_MANIFEST, + /** + * Device has programmed its memories and is waiting for a USB reset or a power on reset. + * (Devices that must enter this state clear bitManifestationTolerant to 0.) + */ + DFU_MANIFEST_WAIT_RESET, + /** + * The device is processing an upload operation. Expecting DFU_UPLOAD requests. + */ + DFU_UPLOAD_IDLE, + /** + * An error has occurred. Awaiting the DFU_CLRSTATUS request. + */ + DFU_ERROR; public static DeviceState fromValue(byte value) { - return values[value]; + return values()[value]; } } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceStatus.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceStatus.java index 9ae30d63..c702112b 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceStatus.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/DeviceStatus.java @@ -15,30 +15,72 @@ */ public enum DeviceStatus { - OK, // No error condition is present - ERR_TARGET, // File is not targeted for use by this device. - ERR_FILE, // File is for this device but fails some vendor-specific verification test. - ERR_WRITE, // Device is unable to write memory. - ERR_ERASE, // Memory erase function failed. - ERR_CHECK_ERASED, // Memory erase check failed. - ERR_PROG, // Program memory function failed. - ERR_VERIFY, // Programmed memory failed verification. - ERR_ADDRESS, // Cannot program memory due to received address that is out of range. - ERR_NOTDONE, // Received DFU_DNLOAD with wLength = 0, but device does not think it has all of the data yet. - ERR_FIRMWARE, // Device’s firmware is corrupt. It cannot return to run-time (non-DFU) operations. - ERR_VENDOR, // iString indicates a vendor-specific error. - ERR_USBR, // Device detected unexpected USB reset signaling. - ERR_POR, // Device detected unexpected power on reset. - ERR_UNKNOWN, // Something went wrong, but the device does not know what it was. - ERR_STALLEDPKT; // Device stalled an unexpected request. + /** + * No error condition is present + */ + OK, + /** + * File is not targeted for use by this device. + */ + ERR_TARGET, + /** + * File is for this device but fails some vendor-specific verification test. + */ + ERR_FILE, + /** + * Device is unable to write memory. + */ + ERR_WRITE, + /** + * Memory erase function failed. + */ + ERR_ERASE, + /** + * Memory erase check failed. + */ + ERR_CHECK_ERASED, + /** + * Program memory function failed. + */ + ERR_PROG, + /** + * Programmed memory failed verification. + */ + ERR_VERIFY, + /** + * Cannot program memory due to received address that is out of range. + */ + ERR_ADDRESS, + /** + * Received DFU_DNLOAD with wLength = 0, but device does not think it has all of the data yet. + */ + ERR_NOTDONE, + /** + * Device’s firmware is corrupt. It cannot return to run-time (non-DFU) operations. + */ + ERR_FIRMWARE, + /** + * iString indicates a vendor-specific error. + */ + ERR_VENDOR, + /** + * Device detected unexpected USB reset signaling. + */ + ERR_USBR, + /** + * Device detected unexpected power on reset. + */ + ERR_POR, + /** + * Something went wrong, but the device does not know what it was. + */ + ERR_UNKNOWN, + /** + * Device stalled an unexpected request. + */ + ERR_STALLEDPKT; - public byte value() { - return (byte) ordinal(); - } - - private static final DeviceStatus[] values = values(); - public static DeviceStatus fromValue(byte value) { - return values[value]; + return values()[value]; } } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Page.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Page.java index d7d90b31..92158670 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Page.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Page.java @@ -24,7 +24,7 @@ public record Page(Segment segment, int startAddress, int count, int pageSize, i * Gets the end address of the page or sector. * @return the end address */ - public int endAddress() { + public int getEndAddress() { return startAddress + count * pageSize; } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/STM32.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/STM32.java index a157ca55..a9f40b57 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/STM32.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/STM32.java @@ -11,5 +11,8 @@ * STM32 specific constants */ public class STM32 { + + private STM32() { } + public static final int FLASH_BASE_ADDRESS = 0x08000000; } diff --git a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Segment.java b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Segment.java index eef8d1fc..f3fdad2b 100644 --- a/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Segment.java +++ b/examples/stm_dfu/src/main/java/net/codecrete/usb/dfu/Segment.java @@ -7,32 +7,37 @@ package net.codecrete.usb.dfu; -import net.codecrete.usb.USBControlTransfer; -import net.codecrete.usb.USBDevice; -import net.codecrete.usb.USBRecipient; -import net.codecrete.usb.USBRequestType; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDevice; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; + +import static net.codecrete.usb.UsbRecipient.DEVICE; +import static net.codecrete.usb.UsbRequestType.STANDARD; /** * Represents a memory segment of the USB device, be it flash memory, RAM or any other type. */ public class Segment { + private static final Pattern SEGMENT_PATTERN = Pattern.compile("@([^/]+)/0x([0-9A-Fa-f]+)/"); + private static final Pattern SECTOR_PATTERN = Pattern.compile(",?(\\d+)\\*(\\d+) ?([BKM]?)(.)"); + /** - * Derives the segments from the USB interface description. + * Decodes the segment information from the USB interface description. * @param device the USB device * @param interfaceNumber the number of the DFU USB interface * @return list of segments */ - public static List getSegments(USBDevice device, int interfaceNumber) { + public static List getSegments(UsbDevice device, int interfaceNumber) { var result = new ArrayList(); // STM uses multiple alternate interface settings to represent segments. - // The alternate interface settings name describes the sectors within the segment. - var configDesc = device.configurationDescriptor(); + // The alternate interface setting name describes the sectors within the segment. + var configDesc = device.getConfigurationDescriptor(); int offset = 0; while (offset < configDesc.length) { if (configDesc[offset + 1] == 4 && (configDesc[offset + 2] & 0xff) == interfaceNumber) { @@ -53,8 +58,8 @@ public static List getSegments(USBDevice device, int interfaceNumber) { * @param index the index of the string descriptor * @return the string */ - private static String getStringDescriptor(USBDevice device, int index) { - var setup = new USBControlTransfer(USBRequestType.STANDARD, USBRecipient.DEVICE, 6, (3 << 8) | index, 0); + private static String getStringDescriptor(UsbDevice device, int index) { + var setup = new UsbControlTransfer(STANDARD, DEVICE, 6, (3 << 8) | index, 0); byte[] stringDesc = device.controlTransferIn(setup, 255); int descLen = stringDesc[0] & 0xff; return new String(stringDesc, 2, descLen - 2, StandardCharsets.UTF_16LE); @@ -68,8 +73,8 @@ private static String getStringDescriptor(USBDevice device, int index) { */ public static Page findPage(List segments, int address) { for (var seg : segments) { - for (var sec : seg.sectors()) { - if (address >= sec.startAddress() && address < sec.endAddress()) { + for (var sec : seg.getSectors()) { + if (address >= sec.startAddress() && address < sec.getEndAddress()) { int offset = address - sec.startAddress(); int pageNum = offset / sec.pageSize(); return new Page(seg, sec.startAddress() + pageNum * sec.pageSize(), 1, sec.pageSize(), sec.attributes()); @@ -80,10 +85,10 @@ public static Page findPage(List segments, int address) { return null; } - private final int altSetting_; - private final String name_; + private final int altSetting; + private final String name; - private final List sectors_; + private final List sectors; /** @@ -96,58 +101,29 @@ public static Page findPage(List segments, int address) { */ private Segment(int altSetting, String segmentDesc) { // The format is described in "UM0424 STM32 USB-FS-Device development kit", ch. 10.3.2 - altSetting_ = altSetting; - sectors_ = new ArrayList(); - int offset = segmentDesc.indexOf('/', 1); - name_ = segmentDesc.substring(1, offset).trim(); - - int startAddress = 0; - while (offset < segmentDesc.length()) { - // parse start address - if (segmentDesc.charAt(offset) == '/') { - int addressEnd = segmentDesc.indexOf('/', offset + 1); - startAddress = (int) Long.parseLong(segmentDesc.substring(offset + 3, addressEnd), 16); - offset = addressEnd + 1; - continue; - } - - // skip comma - if (segmentDesc.charAt(offset) == ',') - offset += 1; - - // parse count - int countEnd = segmentDesc.indexOf('*', offset); - int count = Integer.parseInt(segmentDesc.substring(offset, countEnd)); - offset = countEnd + 1; - - // parse sector size - int sizeEnd = offset; - while (Character.isDigit(segmentDesc.charAt(sizeEnd))) - sizeEnd += 1; - int size = Integer.parseInt(segmentDesc.substring(offset, sizeEnd)); - offset = sizeEnd; - - // skip whitespace - while (segmentDesc.charAt(offset) == ' ') - offset += 1; - - // parse unit - char unitChar = segmentDesc.charAt(offset); - if (unitChar == 'B') { - offset += 1; - } else if (unitChar == 'K') { + this.altSetting = altSetting; + sectors = new ArrayList<>(); + + var match = SEGMENT_PATTERN.matcher(segmentDesc); + if (!match.find()) + throw new DFUException("Invalid segment description: " + segmentDesc); + this.name = match.group(1).trim(); + var startAddress = (int) Long.parseLong(match.group(2), 16); + + match = SECTOR_PATTERN.matcher(segmentDesc.substring(match.end())); + while (match.find()) { + var count = Integer.parseInt(match.group(1)); + var size = Integer.parseInt(match.group(2)); + var multiplier = match.group(3); + var attributes = match.group(4).charAt(0) - 0x60; + + if (multiplier.equals("K")) { size *= 1024; - offset += 1; - } else if (unitChar == 'M') { + } else if (multiplier.equals("M")) { size *= 1024 * 1024; - offset += 1; } - // parse sector attributes - int sectorAttrs = segmentDesc.charAt(offset) - 0x40; - offset += 1; - - sectors_.add(new Page(this, startAddress, count, size, sectorAttrs)); + sectors.add(new Page(this, startAddress, count, size, attributes)); startAddress += size; } } @@ -156,23 +132,23 @@ private Segment(int altSetting, String segmentDesc) { * Gets the alternative interface setting number * @return the setting number */ - public int altSetting() { - return altSetting_; + public int getAltSetting() { + return altSetting; } /** * Gets the segment name. * @return the name */ - public String name() { - return name_; + public String getName() { + return name; } /** * Gets the sectors withing the segment * @return list of sectors */ - public List sectors() { - return sectors_; + public List getSectors() { + return sectors; } } diff --git a/java-does-usb/.mvn/wrapper/maven-wrapper.jar b/java-does-usb/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index cb28b0e3..00000000 Binary files a/java-does-usb/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/java-does-usb/.mvn/wrapper/maven-wrapper.properties b/java-does-usb/.mvn/wrapper/maven-wrapper.properties index ac184013..d58dfb70 100644 --- a/java-does-usb/.mvn/wrapper/maven-wrapper.properties +++ b/java-does-usb/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/java-does-usb/jextract/README.md b/java-does-usb/jextract/README.md index d700e3a8..79d0f270 100644 --- a/java-does-usb/jextract/README.md +++ b/java-does-usb/jextract/README.md @@ -1,31 +1,21 @@ # Code Generation with *jextract* -Some of the binding code for accessing native functions and data structures is generated with [jextract](https://jdk.java.net/jextract/). The tool is still under construction and has its limitations. +A major part of the binding code for accessing native functions and data structures is generated with [jextract](https://jdk.java.net/jextract/). *jextract* is not bundled with the JDK. The binaries can be downloaded from [jdk.java.net/jextract](https://jdk.java.net/jextract/) -In order to generate the code, the scripts in the subdirectories have to be run (`linux/gen_linux.sh`, `macos/gen_macos.sh` and `/windowsgen_win.cmd`). Each script has to be run on the particular operating system. +In order to generate the code, the scripts in the subdirectories have to be run (`linux/gen_linux.sh`, `macos/gen_macos.sh` and `windows/gen_win.cmd`). Each script has to be run on the particular operating system. The scripts expect the *jextract* binary to be in a *jextract* directory at the same parent directory as the *Java Does USB* project. If that is not the case, the *jextract* path can be modified at the top of the scripts. -The code is generated in directories below `gen`, i.e. `main/java/net/codecrete/usb/linux/gen` and similar for the other operating systems. For each library (`xxx.so` or `xxx.dll`) and each macOS framework, a separate package is created. +The code is generated in directories below `gen`, i.e. `main/java/net/codecrete/usb/linux/gen` and similarly for the other operating systems. For each library (`xxx.so` or `xxx.dll`) and each macOS framework, a separate package is created. -The scripts explicitly specify the functions, structs etc. to include as generating code for entire operating system header files can result in an excessive amount of Java source files and classes. +The scripts explicitly specify the functions, structs etc. to include as generating code for entire operating system header files will result in an excessive amount of Java source files and classes. -The resulting code is then committed to the source code repository. Before the commit, imports are cleaned up to get rid of superfluous imports. Most IDEs provide a convenient command to execute this on entire directories. +The resulting code is then committed to the source code repository. ## General limitations -- The binaries for *jextract* on https://jdk.java.net/jextract/ have not been updated for JDK 21. So it must be built from source. Instructions can be found at [Building & Testing](https://github.com/openjdk/jextract#building--testing). - - According to the jextract mailing list, it would be required to create separate code for Intel x64 and ARM64 architecture. And jextract would need to be run on each architecture separately (no cross-compilation). Fortunately, this doesn't seem to be the case. Linux code generated on Intel x64 also runs on ARM64 without change. The same holds for macOS. However, jextract needs to be run on each operating system separately. -- JDK 20 introduced a new feature for saving the thread-specific error values (`GetLastError()` on Windows, `errno` on Linux). To use it, an additional parameter must be added to function calls. Unfortunately, this is not yet supported by jextract. So a good number of function bindings have to be written manually. - -- `typedef` and `struct`: - - 1. If only the `typedef` is included (`--include-typedef`), an empty Java class is generated. - 2. If both *typedef* and the `struct` it refers to are included, the `typedef` class inherits from the `struct` class, which contains all the `struct` members. - 3. If the `typedef` refers to an unnamed `struct`, the generated class contains all the `struct` members. - - Case 1 looks like a bug. +- The *Foreign Function And Memory* API has the abilitiy to save the thread-specific error values (`GetLastError()` on Windows, `errno` on Linux). This is required as the JVM calls operating system functions as well, which overwrite the result values. To save the values, an additional parameter must be added to function calls. Unfortunately, this is not supported by jextract. So a good number of function bindings have to be written manually. - *jextract* is not really transparent about what it does. It often skips elements without providing any information. In particular, it will silently skip a requested element in these cases: @@ -36,6 +26,7 @@ The resulting code is then committed to the source code repository. Before the c - `--include-typedef mystruct` if `mystruct` is actually a `struct`. - `--include-typedef mytypedef` if `mytypedef` is a `typedef` for a primitive type. +- *jextract* resolves all _typedef_s to their actual types. So this library does not use any _--include-typedef_ option. And there does not seem any obvious use for it beyond cosmetics. ## Linux @@ -48,66 +39,44 @@ sudo apt-get install libudev-dev On Linux, the limitations are: -- `usbdevice_fs.h`: The macro `USBDEVFS_CONTROL` and all similar ones are not generated. They are probably considered function-like macros. *jextract* does not generate code for function-like macros. But `USBDEVFS_CONTROL` evaluates to a constant. +- `usbdevice_fs.h`: The macro `USBDEVFS_CONTROL` and all similar ones are not generated. They are probably considered function-like macros. *jextract* does not generate code for function-like macros. `USBDEVFS_CONTROL` would evaluate to a constant. - `sd-device.h` (header file for *libsystemd*): *jextract* fails with *"Error: /usr/include/inttypes.h:290:8: error: unknown type name 'intmax_t'"*. The reason is yet unknown. This code is currently not needed as *libudev* is used instead of *libsystemd*. They are related, *libsystemd* is the future solution, but it is missing support for monitoring devices. -- `libudev.h`: After code generation, the class `RuntimeHelper.java` in `.../linux/gen/udev` must be manually modified as the code to access the library does not work for the directory the library is located in. So replace: - -``` -System.loadLibrary("udev"); -SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); -``` - -with: - -``` -SymbolLookup loaderLookup = SymbolLookup.libraryLookup("libudev.so", MemorySession.openImplicit()); -``` ## MacOS Most of the required native functions on macOS are part of a framework. Frameworks internally have a more complex file organization of header and binary files than appears from the outside. Thus, they require a special logic to locate framework header files. *clang* supports it with the `-F`. *jextract* allows to specify the options via `compiler_flags.txt` file. Since the file must be in the local directory and since it does not apply to Linux and Windows, separate directories must be used for the operating systems. -The generated code has the same problem as the Linux code for *udev*. It must be manually changed to use `SymbolLookup.libraryLookup()` for the libraries `CoreFoundation.framework/CoreFoundation` and `IOKit.framework/IOKit` respectively. ## Windows -Most Windows SDK header files are not independent. They require that `Windows.h` is included first. So instead of specifying the target header files directly, a helper header file (`windows_headers.h` in this directory) is specified. - -Compared to Linux and macOS, the code generation on Windows is very slow (about 1 min vs 3 seconds). And jextract crashes sometimes. - -The known limitations are: +The Windows code is not generated with _jextract_ but with [Windows API Generator](https://github.com/manuelbl/WindowsApiGenerator) +instead. It is run as a Maven plugin. The generated code is not committed to GitHub. -- Variable size `struct`: Several Windows struct are of variable size. The last member is an array. The `struct` definition specifies array length 1. But you are expected to allocate more space depending on the actual array size you need. *jextract* generates code for array length 1 and checks the length when the members are accessed. So the generated code is difficult to use. Variable size `struct`s are a pain - in any language. - -- GUID constants like `GUID_DEVINTERFACE_USB_DEVICE` do not work. While code is generated, the code fails at run-time as it is unable to locate the symbol. This is due to the fact that `GUID_DEVINTERFACE_USB_DEVICE` actually resolve to a variable definition and not to a variable declaration. The GUID constant is not contained in any library; instead the header files use linkage options to generate the constant in the callers code, which does not work with FFM. Such constants should be skipped by *jextract*. - -- *jextract* is a batch script and turns off *echo mode*. If a single batch scripts has multiple calls of *jextract*, two things need to be considered: - - - If the regular command interpreter `cmd.exe` is used, *jextract* must be called using `call`, i.e. `call jextract header.h`. - - If *PowerShell* is used instead, `call` is not needed but *PowerShell* must be configured to allow the execution of scripts. - - *jextract* turns off *echo mode*. So the first call will behave differently than the following calls. +Windows API Generator supports call state capturing (`GetLastError()`), structs with a +variable size, GUID and device property key (`DEVPKEY`) constants etc. ## Code Size *jextract* generates a comprehensive set of methods for each function, struct, struct member etc. Most of it will not be used as a typical application just uses a subset of struct members, might only read or write them etc. So a considerable amount of code is generated. For some types, it's a bit excessive. -The worst example is [`IOUSBInterfaceStruct190`](https://github.com/manuelbl/JavaDoesUSB/blob/main/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java) (macOS). This is a `struct` consisting of about 50 member functions. It's basically a vtable of a C++ class. For this single `struct`, *jextract* generates codes resulting in 70 class files with a total size of 227kByte.. +The worst example is [`IOUSBInterfaceStruct190`](https://github.com/manuelbl/JavaDoesUSB/blob/main/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java) (macOS). This is a `struct` consisting of about 50 member functions. It's basically a vtable of a C++ class. For this single `struct`, *jextract* generates codes resulting in 100 class files with a total size of 213kByte. + +The table below shows class file size statistics for version 1.2.2 of the library: -The table below shows statistics for version 0.6.0 of the library: +| Operating Systems | Manually Written | % | Generated | % | Total | % | +|-------------------|-----------------:|------:|----------:|------:|----------:|--------:| +| Linux | 58,393 | 4.5% | 154,398 | 11.8% | 212,791 | 16.3% | +| macOS | 81,441 | 6.2% | 427,258 | 32.8% | 508,699 | 39.0% | +| Windows | 84,099 | 6.5% | 384,452 | 29.5% | 468,551 | 35.9% | +| Common | 113,568 | 8.7% | | | 113,568 | 8.7% | +| Grand Total | 337,501 | 25.9% | 966,108 | 74.1% | 1,303,609 | 100.0% | -| Operating Systems | Manually Created | % | Generated | % | Total | % | -|-------------------|-----------------:|-------:|----------:|-------:|----------:|--------:| -| Linux | 48,516 | 3.64% | 197,169 | 14.79% | 245,685 | 18.42% | -| macOS | 78,718 | 5.90% | 546,907 | 41.01% | 625,625 | 46.91% | -| Windows | 104,811 | 7.86% | 256,079 | 19.20% | 360,890 | 27.06% | -| Common | 101,364 | 7.60% | | | 101,364 | 7.60% | -| Grand Total | 333,409 | 25.00% | 1,000,155 | 75.00% | 1,333,564 | 100.00% | -*Code Size (compiled), in bytes and percentage of total size* +*Class File Size (compiled), in bytes and percentage of total size* If *jextract* could generate code for error state capturing, there would be even more generated and less manually written code. diff --git a/java-does-usb/jextract/linux/epoll.h b/java-does-usb/jextract/linux/epoll.h new file mode 100644 index 00000000..c7c68b45 --- /dev/null +++ b/java-does-usb/jextract/linux/epoll.h @@ -0,0 +1,3 @@ +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +#include diff --git a/java-does-usb/jextract/linux/gen_linux.sh b/java-does-usb/jextract/linux/gen_linux.sh index 31b8654f..7e5eb5ec 100755 --- a/java-does-usb/jextract/linux/gen_linux.sh +++ b/java-does-usb/jextract/linux/gen_linux.sh @@ -1,34 +1,41 @@ #!/bin/sh -JEXTRACT=../../../../jextract/build/jextract/bin/jextract +JEXTRACT=../../../../jextract/bin/jextract + +rm -rf ../../src/main/java/net/codecrete/usb/linux/gen # errno.h -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name errno \ --target-package net.codecrete.usb.linux.gen.errno \ --include-constant EPIPE \ --include-constant EAGAIN \ + --include-constant EBADF \ + --include-constant ECANCELED \ --include-constant EINVAL \ --include-constant ENODEV \ + --include-constant EINTR \ + --include-constant ENOENT \ /usr/include/errno.h # string.h -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name string \ --target-package net.codecrete.usb.linux.gen.string \ --include-function strerror \ /usr/include/string.h # fcntl.h -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name fcntl \ --target-package net.codecrete.usb.linux.gen.fcntl \ --include-constant O_CLOEXEC \ --include-constant O_RDWR \ + --include-constant FD_CLOEXEC \ /usr/include/fcntl.h # unistd.h -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name unistd \ --target-package net.codecrete.usb.linux.gen.unistd \ --include-function close \ @@ -36,7 +43,7 @@ $JEXTRACT --source --output ../../src/main/java \ # usbdevice_fs.h # Missing constants like USBDEVFS_CLAIMINTERFACE -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name usbdevice_fs \ --target-package net.codecrete.usb.linux.gen.usbdevice_fs \ --include-struct usbdevfs_bulktransfer \ @@ -45,16 +52,7 @@ $JEXTRACT --source --output ../../src/main/java \ --include-struct usbdevfs_urb \ --include-struct usbdevfs_disconnect_claim \ --include-struct usbdevfs_ioctl \ - --include-constant USBDEVFS_CONTROL \ - --include-constant USBDEVFS_BULK \ - --include-constant USBDEVFS_CLAIMINTERFACE \ - --include-constant USBDEVFS_RELEASEINTERFACE \ - --include-constant USBDEVFS_SETINTERFACE \ - --include-constant USBDEVFS_CLEAR_HALT \ - --include-constant USBDEVFS_SUBMITURB \ - --include-constant USBDEVFS_DISCARDURB \ - --include-constant USBDEVFS_REAPURB \ - --include-constant USBDEVFS_DISCONNECT_CLAIM \ + --include-struct usbdevfs_iso_packet_desc \ --include-constant USBDEVFS_URB_TYPE_INTERRUPT \ --include-constant USBDEVFS_URB_TYPE_CONTROL \ --include-constant USBDEVFS_URB_TYPE_BULK \ @@ -64,10 +62,10 @@ $JEXTRACT --source --output ../../src/main/java \ # libudev.h # (install libudev-dev if file is missing) -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ --header-class-name udev \ --target-package net.codecrete.usb.linux.gen.udev \ - -l udev \ + -l :libudev.so.1 \ --include-function udev_new \ --include-function udev_enumerate_new \ --include-function udev_enumerate_add_match_subsystem \ @@ -89,14 +87,14 @@ $JEXTRACT --source --output ../../src/main/java \ --include-function udev_monitor_get_fd \ /usr/include/libudev.h -# poll.h -$JEXTRACT --source --output ../../src/main/java \ - --header-class-name poll \ - --target-package net.codecrete.usb.linux.gen.poll \ - --include-function poll \ - --include-struct pollfd \ - --include-constant POLLIN \ - --include-constant POLLOUT \ - --include-constant POLLERR \ - /usr/include/poll.h +# epoll.h +$JEXTRACT --output ../../src/main/java \ + --header-class-name epoll \ + --target-package net.codecrete.usb.linux.gen.epoll \ + --include-constant EPOLL_CTL_ADD \ + --include-constant EPOLL_CTL_DEL \ + --include-constant EPOLLIN \ + --include-constant EPOLLOUT \ + --include-constant EPOLLWAKEUP \ + epoll.h diff --git a/java-does-usb/jextract/macos/gen_macos.sh b/java-does-usb/jextract/macos/gen_macos.sh index c74b5864..d74e38c2 100755 --- a/java-does-usb/jextract/macos/gen_macos.sh +++ b/java-does-usb/jextract/macos/gen_macos.sh @@ -1,17 +1,19 @@ #!/bin/sh -JEXTRACT=../../../../jextract/build/jextract/bin/jextract +JEXTRACT=../../../../jextract/bin/jextract # If SDK_DIR is changed, it needs to be changed in compile_flags.txt as well. SDK_DIR=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk +rm -rf ../../src/main/java/net/codecrete/usb/macos/gen + # CoreFoundation -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ -I $SDK_DIR/usr/include \ - -lCoreFoundation.framework \ + -l :/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation \ --header-class-name CoreFoundation \ --target-package net.codecrete.usb.macos.gen.corefoundation \ - --include-typedef CFRange \ - --include-typedef CFUUIDBytes \ + --include-struct CFRange \ + --include-struct CFUUIDBytes \ --include-function CFUUIDCreateFromUUIDBytes \ --include-function CFRelease \ --include-function CFStringGetLength \ @@ -25,14 +27,20 @@ $JEXTRACT --source --output ../../src/main/java \ --include-function CFRunLoopAddSource \ --include-function CFRunLoopRemoveSource \ --include-function CFRunLoopRun \ + --include-function CFMessagePortCreateLocal \ + --include-function CFMessagePortCreateRunLoopSource \ + --include-function CFMessagePortCreateRemote \ + --include-function CFMessagePortSendRequest \ + --include-function CFDataCreate \ + --include-function CFDataGetBytePtr \ --include-function CFUUIDGetUUIDBytes \ --include-constant kCFNumberSInt32Type \ cf_helper.h # IOKit -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ -I $SDK_DIR/usr/include \ - -lIOKit.framework \ + -l :/System/Library/Frameworks/IOKit.framework/IOKit \ --header-class-name IOKit \ --target-package net.codecrete.usb.macos.gen.iokit \ --include-var kIOMasterPortDefault \ @@ -42,7 +50,6 @@ $JEXTRACT --source --output ../../src/main/java \ --include-constant kIOReturnExclusiveAccess \ --include-var kCFRunLoopDefaultMode \ --include-struct IOCFPlugInInterfaceStruct \ - --include-typedef IOCFPlugInInterface \ --include-function IOObjectRelease \ --include-function IOIteratorNext \ --include-function IOCreatePlugInInterfaceForService \ @@ -53,23 +60,26 @@ $JEXTRACT --source --output ../../src/main/java \ --include-function IOServiceAddMatchingNotification \ --include-function IOServiceMatching \ --include-struct IOUSBDeviceStruct187 \ - --include-typedef IOUSBDeviceInterface187 \ --include-constant kIOUSBFindInterfaceDontCare \ - --include-typedef IOUSBFindInterfaceRequest \ - --include-typedef IOUSBDevRequest \ + --include-struct IOUSBFindInterfaceRequest \ + --include-struct IOUSBDevRequest \ --include-struct IOUSBInterfaceStruct190 \ - --include-typedef IOUSBInterfaceInterface190 \ --include-constant kIOUSBTransactionTimeout \ --include-constant kIOReturnAborted \ --include-constant kIOUSBPipeStalled \ --include-constant kUSBReEnumerateCaptureDeviceMask \ --include-constant kUSBReEnumerateReleaseDeviceMask \ + --include-struct CFUUIDBytes \ iokit_helper.h # mach.h -$JEXTRACT --source --output ../../src/main/java \ +$JEXTRACT --output ../../src/main/java \ -I $SDK_DIR/usr/include \ --header-class-name mach \ --target-package net.codecrete.usb.macos.gen.mach \ --include-function mach_error_string \ $SDK_DIR/usr/include/mach/mach.h + +sed -i '' -E -f remove_fp_upcall.sed ../../src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceStruct187.java +sed -i '' -E -f remove_fp_upcall.sed ../../src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java +sed -i '' -E -f remove_fp_upcall.sed ../../src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterfaceStruct.java diff --git a/java-does-usb/jextract/macos/remove_fp_upcall.sed b/java-does-usb/jextract/macos/remove_fp_upcall.sed new file mode 100644 index 00000000..d90e01d3 --- /dev/null +++ b/java-does-usb/jextract/macos/remove_fp_upcall.sed @@ -0,0 +1,6 @@ +/The function pointer signature/,/ \}/ { + s/^.*function pointer signature.*$/ *\//p + d + +} +/MethodHandle UP\$MH = /,/ \}/d diff --git a/java-does-usb/jextract/windows/gen_win.cmd b/java-does-usb/jextract/windows/gen_win.cmd deleted file mode 100644 index a4084d2c..00000000 --- a/java-does-usb/jextract/windows/gen_win.cmd +++ /dev/null @@ -1,145 +0,0 @@ -set JEXTRACT=..\..\..\..\jextract\build\jextract\bin\jextract.bat -set SDK_DIR=C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0 - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l Kernel32 ^ - --header-class-name Kernel32 ^ - --target-package net.codecrete.usb.windows.gen.kernel32 ^ - --include-function CloseHandle ^ - --include-function GetModuleHandleW ^ - --include-function FormatMessageW ^ - --include-function LocalFree ^ - --include-constant ERROR_NO_MORE_ITEMS ^ - --include-constant ERROR_MORE_DATA ^ - --include-constant ERROR_INSUFFICIENT_BUFFER ^ - --include-constant ERROR_FILE_NOT_FOUND ^ - --include-constant ERROR_GEN_FAILURE ^ - --include-constant ERROR_NOT_FOUND ^ - --include-constant ERROR_IO_PENDING ^ - --include-constant GENERIC_READ ^ - --include-constant GENERIC_WRITE ^ - --include-constant FILE_SHARE_READ ^ - --include-constant FILE_SHARE_WRITE ^ - --include-constant FILE_ATTRIBUTE_NORMAL ^ - --include-constant FILE_FLAG_OVERLAPPED ^ - --include-constant OPEN_EXISTING ^ - --include-constant FORMAT_MESSAGE_ALLOCATE_BUFFER ^ - --include-constant FORMAT_MESSAGE_FROM_SYSTEM ^ - --include-constant FORMAT_MESSAGE_IGNORE_INSERTS ^ - --include-constant FORMAT_MESSAGE_FROM_HMODULE ^ - --include-constant INFINITE ^ - --include-struct _GUID ^ - --include-typedef GUID ^ - --include-struct _OVERLAPPED ^ - --include-typedef OVERLAPPED ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l SetupAPI ^ - --header-class-name SetupAPI ^ - --target-package net.codecrete.usb.windows.gen.setupapi ^ - --include-function SetupDiDestroyDeviceInfoList ^ - --include-function SetupDiDeleteDeviceInterfaceData ^ - --include-struct _SP_DEVINFO_DATA ^ - --include-typedef SP_DEVINFO_DATA ^ - --include-struct _SP_DEVICE_INTERFACE_DATA ^ - --include-typedef SP_DEVICE_INTERFACE_DATA ^ - --include-struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W ^ - --include-typedef SP_DEVICE_INTERFACE_DETAIL_DATA_W ^ - --include-struct _DEVPROPKEY ^ - --include-typedef DEVPROPKEY ^ - --include-constant DIGCF_PRESENT ^ - --include-constant DIGCF_DEVICEINTERFACE ^ - --include-constant DEVPROP_TYPE_UINT32 ^ - --include-constant DEVPROP_TYPE_STRING ^ - --include-constant DEVPROP_TYPEMOD_LIST ^ - --include-constant DICS_FLAG_GLOBAL ^ - --include-constant DIREG_DEV ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - --header-class-name USBIoctl ^ - --target-package net.codecrete.usb.windows.gen.usbioctl ^ - --include-struct _USB_NODE_CONNECTION_INFORMATION_EX ^ - --include-typedef USB_NODE_CONNECTION_INFORMATION_EX ^ - --include-struct _USB_DESCRIPTOR_REQUEST ^ - --include-typedef USB_DESCRIPTOR_REQUEST ^ - --include-constant IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX ^ - --include-constant IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l User32 ^ - --header-class-name User32 ^ - --target-package net.codecrete.usb.windows.gen.user32 ^ - --include-function DefWindowProcW ^ - --include-constant DEVICE_NOTIFY_WINDOW_HANDLE ^ - --include-constant HWND_MESSAGE ^ - --include-constant WM_DEVICECHANGE ^ - --include-constant DBT_DEVICEARRIVAL ^ - --include-constant DBT_DEVICEREMOVECOMPLETE ^ - --include-constant DBT_DEVTYP_DEVICEINTERFACE ^ - --include-struct tagMSG ^ - --include-typedef MSG ^ - --include-struct tagWNDCLASSEXW ^ - --include-typedef WNDCLASSEXW ^ - --include-struct _DEV_BROADCAST_HDR ^ - --include-typedef DEV_BROADCAST_HDR ^ - --include-struct _DEV_BROADCAST_DEVICEINTERFACE_W ^ - --include-typedef DEV_BROADCAST_DEVICEINTERFACE_W ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l Winusb ^ - --header-class-name WinUSB ^ - --target-package net.codecrete.usb.windows.gen.winusb ^ - --include-function WinUsb_Free ^ - --include-constant PIPE_TRANSFER_TIMEOUT ^ - --include-constant RAW_IO ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l Advapi32 ^ - --header-class-name Advapi32 ^ - --target-package net.codecrete.usb.windows.gen.advapi32 ^ - --include-function RegQueryValueExW ^ - --include-function RegCloseKey ^ - --include-constant KEY_READ ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - -l Ole32 ^ - --header-class-name Ole32 ^ - --target-package net.codecrete.usb.windows.gen.ole32 ^ - --include-function CLSIDFromString ^ - windows_headers.h - -call %JEXTRACT% --source --output ../../src/main/java ^ - -D _AMD64_ -D _M_AMD64=100 -D UNICODE -D _UNICODE ^ - -I "%SDK_DIR%\um" ^ - -I "%SDK_DIR%\shared" ^ - --header-class-name NtDll ^ - --target-package net.codecrete.usb.windows.gen.ntdll ^ - --include-constant STATUS_UNSUCCESSFUL ^ - windows_headers.h diff --git a/java-does-usb/jextract/windows/windows_headers.h b/java-does-usb/jextract/windows/windows_headers.h deleted file mode 100644 index 171b98ee..00000000 --- a/java-does-usb/jextract/windows/windows_headers.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include -#include -#include -#include -#include diff --git a/java-does-usb/mvnw b/java-does-usb/mvnw index 8d937f4c..19529ddf 100755 --- a/java-does-usb/mvnw +++ b/java-does-usb/mvnw @@ -19,290 +19,241 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.2.0 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.2 # # Optional ENV vars # ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /usr/local/etc/mavenrc ] ; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false +# OS specific support. +native_path() { printf %s\\n "$1"; } case "$(uname)" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home"; export JAVA_HOME - fi - fi - ;; +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; esac -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && - JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin ; then - javaHome="$(dirname "\"$javaExecutable\"")" - javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "\"$javaExecutable\"")" - fi - javaHome="$(dirname "\"$javaExecutable\"")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" else JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi fi else - JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi +} - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$(cd "$wdir/.." || exit 1; pwd) - fi - # end of workaround +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done - printf '%s' "$(cd "$basedir" || exit 1; pwd)" + printf %x\\n $h } -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' < "$1" - fi +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 } -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" } -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1; +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT else - log "Couldn't find $wrapperJarPath, downloading it ..." + die "cannot create temp dir" +fi - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; - esac - done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" +mkdir -p -- "${MAVEN_HOME%/*}" - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - if command -v wget > /dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -########################################################################################## -# End of extension -########################################################################################## -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; - esac -done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then - wrapperSha256Result=true +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true fi - elif command -v shasum > /dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then - wrapperSha256Result=true + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 exit 1 fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 exit 1 fi fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] && - CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/java-does-usb/mvnw.cmd b/java-does-usb/mvnw.cmd index c4586b56..249bdf38 100644 --- a/java-does-usb/mvnw.cmd +++ b/java-does-usb/mvnw.cmd @@ -1,3 +1,4 @@ +<# : batch portion @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @@ -18,188 +19,131 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir +@REM Apache Maven Wrapper startup batch script, version 3.3.2 @REM @REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output @REM ---------------------------------------------------------------------------- -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) ) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/java-does-usb/pom.xml b/java-does-usb/pom.xml index 32b756cf..e8ad6aec 100644 --- a/java-does-usb/pom.xml +++ b/java-does-usb/pom.xml @@ -6,14 +6,17 @@ net.codecrete.usb java-does-usb - 0.6.0-SNAPSHOT + 1.3.1-SNAPSHOT - 21 - 21 + 25 + 25 UTF-8 + 0.8.0 + jar + Java Does USB https://github.com/manuelbl/JavaDoesUSB Access USB devices from Java without additional libraries @@ -38,44 +41,113 @@ https://github.com/manuelbl/JavaDoesUSB - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - + + net.codecrete.windows-api + windowsapi-maven-plugin + + + + windows-api + + + + CLSIDFromString + CreateFileW + CreateIoCompletionPort + CreateWindowExW + DefWindowProcW + DeviceIoControl + FormatMessageW + GetMessageW + GetModuleHandleW + GetQueuedCompletionStatus + LocalFree + RegCloseKey + RegQueryValueExW + RegisterClassExW + RegisterDeviceNotificationW + SetupDiCreateDeviceInfoList + SetupDiDeleteDeviceInterfaceData + SetupDiDestroyDeviceInfoList + SetupDiEnumDeviceInfo + SetupDiEnumDeviceInterfaces + SetupDiGetClassDevsW + SetupDiGetDeviceInterfaceDetailW + SetupDiGetDevicePropertyW + SetupDiOpenDevRegKey + SetupDiOpenDeviceInfoW + SetupDiOpenDeviceInterfaceW + WinUsb_AbortPipe + WinUsb_Free + WinUsb_GetAssociatedInterface + WinUsb_Initialize + WinUsb_ReadPipe + WinUsb_ResetPipe + WinUsb_SetCurrentAlternateSetting + WinUsb_SetPipePolicy + WinUsb_WritePipe + + + DEV_BROADCAST_DEVICEINTERFACE_W + DEV_BROADCAST_HDR + USB_DESCRIPTOR_REQUEST + USB_NODE_CONNECTION_INFORMATION_EX + + + DEV_BROADCAST_HDR_DEVICE_TYPE + FORMAT_MESSAGE_OPTIONS + GENERIC_ACCESS_RIGHTS + REG_SAM_FLAGS + SETUP_DI_PROPERTY_CHANGE_SCOPE + + + DBT_DEVICEARRIVAL + DBT_DEVICEREMOVECOMPLETE + DEVPKEY_Device_Address + DEVPKEY_Device_Children + DEVPKEY_Device_HardwareIds + DEVPKEY_Device_InstanceId + DEVPKEY_Device_Parent + DEVPKEY_Device_Service + DIREG_DEV + GUID_DEVINTERFACE_USB_DEVICE + GUID_DEVINTERFACE_USB_HUB + HWND_MESSAGE + INFINITE + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION + IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX + STATUS_UNSUCCESSFUL + USB_REQUEST_GET_DESCRIPTOR + WM_DEVICECHANGE + + + + + org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.12.1 - 21 - - --enable-preview - - 21 - 21 + 25 + 25 + 25 org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 - --enable-preview --enable-native-access=ALL-UNNAMED + --enable-native-access=ALL-UNNAMED org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.3 attach-javadocs @@ -85,9 +157,9 @@ - 21 - --enable-preview + 25 ${java.home}/bin/javadoc + net.codecrete.usb.linux.gen.*:net.codecrete.usb.macos.gen.*:windows.*:system @@ -117,36 +189,58 @@
+ + org.sonatype.central + central-publishing-maven-plugin + ${sonatype-central-publishing.version} + true + + central + true + +
- org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ossrh - https://s01.oss.sonatype.org/ - true - + net.codecrete.windows-api + windowsapi-maven-plugin + 0.8.5
+ + org.jetbrains + annotations + 24.1.0 + compile + org.junit.jupiter junit-jupiter - 5.9.3 + 5.10.2 test org.assertj assertj-core - 3.24.2 + 3.25.3 + test + + + org.tinylog + tinylog-impl + 2.7.0 + test + + + org.tinylog + jsl-tinylog + 2.7.0 test diff --git a/java-does-usb/src/main/java/module-info.java b/java-does-usb/src/main/java/module-info.java index cf4daec9..496c87ec 100644 --- a/java-does-usb/src/main/java/module-info.java +++ b/java-does-usb/src/main/java/module-info.java @@ -9,5 +9,6 @@ * Java Does USB – work with USB devices */ module net.codecrete.usb { + requires org.jetbrains.annotations; exports net.codecrete.usb; } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USB.java b/java-does-usb/src/main/java/net/codecrete/usb/USB.java deleted file mode 100644 index 59564730..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/USB.java +++ /dev/null @@ -1,124 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb; - -import net.codecrete.usb.common.USBDeviceRegistry; -import net.codecrete.usb.linux.LinuxUSBDeviceRegistry; -import net.codecrete.usb.macos.MacosUSBDeviceRegistry; -import net.codecrete.usb.windows.WindowsUSBDeviceRegistry; - -import java.util.List; -import java.util.Optional; -import java.util.function.Consumer; - -/** - * Provides access to USB devices. - */ -public class USB { - - private static USBDeviceRegistry createInstance() { - var osName = System.getProperty("os.name"); - var osArch = System.getProperty("os.arch"); - - USBDeviceRegistry impl; - if (osName.equals("Mac OS X") && (osArch.equals("x86_64") || osArch.equals("aarch64"))) { - impl = new MacosUSBDeviceRegistry(); - } else if (osName.startsWith("Windows") && osArch.equals("amd64")) { - impl = new WindowsUSBDeviceRegistry(); - } else if (osName.equals("Linux") && (osArch.equals("amd64") || osArch.equals("aarch64"))) { - impl = new LinuxUSBDeviceRegistry(); - } else { - throw new UnsupportedOperationException(String.format( - "Java Does USB has no implementation for architecture %s/%s", - osName, osArch)); - } - return impl; - } - - private static USBDeviceRegistry singletonInstance = null; - - private static synchronized USBDeviceRegistry instance() { - if (singletonInstance == null) { - singletonInstance = createInstance(); - singletonInstance.start(); - } - return singletonInstance; - } - - // Private, so no instance can be created - private USB() { - } - - /** - * Gets a list of all connected USB devices. - * - *

- * Depending on the operating system, the list might or might not include - * USB hubs and USB host controllers. - *

- * - * @return list of USB devices - */ - public static List getAllDevices() { - return instance().getAllDevices(); - } - - /** - * Gets a list of connected USB devices matching the specified predicate. - * - * @param predicate device predicate - * @return list of USB devices - */ - public static List getDevices(USBDevicePredicate predicate) { - return instance().getAllDevices().stream().filter(predicate::matches).toList(); - } - - /** - * Gets the first connected USB device matching the specified predicate. - * - * @param predicate device predicate - * @return optional USB device - */ - public static Optional getDevice(USBDevicePredicate predicate) { - return instance().getAllDevices().stream().filter(predicate::matches).findFirst(); - } - - /** - * Gets the first connected USB device with the specified vendor and product ID. - * - * @param vendorId vendor ID - * @param productId product ID - * @return optional USB device - */ - public static Optional getDevice(int vendorId, int productId) { - return getDevice(device -> device.vendorId() == vendorId && device.productId() == productId); - } - - /** - * Sets the handler to be called when a USB device is connected. - * - * @param handler handler function, or {@code null} to remove a previous handler - */ - public static void setOnDeviceConnected(Consumer handler) { - instance().setOnDeviceConnected(handler); - } - - /** - * Sets the handler to be called when a USB device is disconnected. - *

- * When the handler is called, the {@link USBDevice} instance has already been closed. - * Descriptive information (such as vendor and product ID, serial number, interfaces, endpoints) - * can still be accessed. - *

- * - * @param handler handler function, or {@code null} to remove a previous handler - */ - public static void setOnDeviceDisconnected(Consumer handler) { - instance().setOnDeviceDisconnected(handler); - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/Usb.java b/java-does-usb/src/main/java/net/codecrete/usb/Usb.java new file mode 100644 index 00000000..b17fc604 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/Usb.java @@ -0,0 +1,153 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb; + +import net.codecrete.usb.common.UsbDeviceRegistry; +import net.codecrete.usb.linux.LinuxUsbDeviceRegistry; +import net.codecrete.usb.macos.MacosUsbDeviceRegistry; +import net.codecrete.usb.windows.WindowsUsbDeviceRegistry; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +/** + * Provides access to USB devices. + */ +public class Usb { + + @SuppressWarnings("java:S1192") + private static UsbDeviceRegistry createInstance() { + var osName = System.getProperty("os.name"); + var osArch = System.getProperty("os.arch"); + + UsbDeviceRegistry impl; + if (osName.equals("Mac OS X") && (osArch.equals("x86_64") || osArch.equals("aarch64"))) { + impl = new MacosUsbDeviceRegistry(); + } else if (osName.startsWith("Windows") && (osArch.equals("amd64") || osArch.equals("aarch64"))) { + impl = new WindowsUsbDeviceRegistry(); + } else if (osName.equals("Linux") && (osArch.equals("amd64") || osArch.equals("aarch64"))) { + impl = new LinuxUsbDeviceRegistry(); + } else { + throw new UnsupportedOperationException(String.format( + "The \"Java Does USB\" library has no implementation for JRE/JDK %s/%s", + osName, osArch)); + } + return impl; + } + + private static UsbDeviceRegistry singletonInstance = null; + + private static synchronized UsbDeviceRegistry instance() { + if (singletonInstance == null) { + singletonInstance = createInstance(); + singletonInstance.start(); + } + return singletonInstance; + } + + // Private, so no instance can be created + private Usb() { + } + + /** + * Gets a list of all connected USB devices. + * + *

+ * Depending on the operating system, the list might or might not include + * USB hubs and USB host controllers. + *

+ * + * @return list of USB devices + */ + public static @NotNull @Unmodifiable Collection getDevices() { + return Collections.unmodifiableCollection(instance().getAllDevices()); + } + + /** + * Gets a list of connected USB devices matching the specified predicate. + * + * @param predicate device predicate + * @return list of USB devices + */ + public static @NotNull @Unmodifiable List findDevices(@NotNull UsbDevicePredicate predicate) { + return instance().getAllDevices().stream().filter(predicate::matches).toList(); + } + + /** + * Gets the first connected USB device matching the specified predicate. + * + * @param predicate device predicate + * @return optional USB device + */ + public static Optional findDevice(@NotNull UsbDevicePredicate predicate) { + return instance().getAllDevices().stream().filter(predicate::matches).findFirst(); + } + + /** + * Gets the first connected USB device with the specified vendor and product ID. + * + * @param vendorId vendor ID + * @param productId product ID + * @return optional USB device + */ + public static Optional findDevice(int vendorId, int productId) { + return findDevice(device -> device.getVendorId() == vendorId && device.getProductId() == productId); + } + + /** + * Sets the handler to be called when a USB device is connected. + *

+ * The handler is called from a background thread. + *

+ *

+ * The handler should not execute any time-consuming operations but rather return quickly. + * While the handler is being executed, maintaining the list of connected devices is paused, + * methods of this class (such as {@link #getDevices()}) will possibly work with an outdated list + * of connected devices and handlers for connect and disconnect events will not be called. + *

+ * + * @param handler handler function, or {@code null} to remove a previous handler + */ + public static void setOnDeviceConnected(@Nullable Consumer handler) { + instance().setOnDeviceConnected(handler); + } + + /** + * Sets the handler to be called when a USB device is disconnected. + *

+ * The handler is called from a background thread. + *

+ *

+ * When the handler is called, the {@link UsbDevice} instance has already been closed. + * Descriptive information (such as vendor and product ID, serial number, interfaces, endpoints) + * can still be accessed. + *

+ *

+ * If the application was communicating with the device when it was disconnected, it will also receive + * an error for those operations. Due to the concurrency of the USB stack, there is no particular order + * for the disconnect event and the transmission errors. + *

+ *

+ * The handler should not execute any time-consuming operations but rather return quickly. + * While the handler is being executed, maintaining the list of connected devices is paused, + * methods of this class (such as {@link #getDevices()}) will possibly work with an outdated list + * of connected devices and handlers for connect and disconnect events will not be called. + *

+ * + * @param handler handler function, or {@code null} to remove a previous handler + */ + public static void setOnDeviceDisconnected(@Nullable Consumer handler) { + instance().setOnDeviceDisconnected(handler); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBAlternateInterface.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbAlternateInterface.java similarity index 70% rename from java-does-usb/src/main/java/net/codecrete/usb/USBAlternateInterface.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbAlternateInterface.java index b0445f9c..835f68aa 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBAlternateInterface.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbAlternateInterface.java @@ -7,6 +7,9 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + import java.util.List; /** @@ -15,16 +18,17 @@ * Instances of this class describe an alternate setting of a USB interface. *

*/ -public interface USBAlternateInterface { +public interface UsbAlternateInterface { /** * Gets the alternate setting number. *

* It is equal to the {@code bAlternateSetting} field of the interface descriptor. + *

* * @return the alternate setting number */ - int number(); + int getNumber(); /** * Gets the interface class. @@ -34,7 +38,7 @@ public interface USBAlternateInterface { * * @return the interface class */ - int classCode(); + int getClassCode(); /** * Gets the interface subclass. @@ -44,7 +48,7 @@ public interface USBAlternateInterface { * * @return the interface subclass */ - int subclassCode(); + int getSubclassCode(); /** * Gets the interface protocol. @@ -54,26 +58,32 @@ public interface USBAlternateInterface { * * @return the interface protocol */ - int protocolCode(); + int getProtocolCode(); /** - * Gets the endpoints of this alternate interface settings. + * Gets the endpoints of this alternate interface setting. *

* The endpoint list does not include endpoint 0, which * is always available and reserved for control transfers. *

+ *

+ * The returned list is sorted by endpoint number. + *

* * @return a list of endpoints. */ - List endpoints(); + @NotNull + @Unmodifiable + List getEndpoints(); /** * Gets the endpoint with the specified number and direction. * * @param endpointNumber endpoint number (in the range between 1 and 127, without the direction bit) * @param direction endpoint direction - * @return the endpoint, or {@code null} if no endpoint with the given number and direction exists + * @return the endpoint + * @exception UsbException if the endpoint does not exist */ - USBEndpoint getEndpoint(int endpointNumber, USBDirection direction); + @NotNull UsbEndpoint getEndpoint(int endpointNumber, UsbDirection direction); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBControlTransfer.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbControlTransfer.java similarity index 79% rename from java-does-usb/src/main/java/net/codecrete/usb/USBControlTransfer.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbControlTransfer.java index ef937118..dbc2e042 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBControlTransfer.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbControlTransfer.java @@ -20,13 +20,13 @@ * * @param requestType request type (bits 5 and 6 of {@code bmRequestType}) * @param recipient recipient (bits 0–4 of {@code bmRequestType}) - * @param request request code (value between 0 and 255, called {@code bRequest} in USB specification) - * @param value value (value between 0 and 65535, called {@code wValue} in USB specification) - * @param index index (value between 0 and 65535, called {@code wIndex} in USB specification). + * @param request request code (value between 0 and 255, called {@code bRequest} in the USB specification) + * @param value value (value between 0 and 65535, called {@code wValue} in the USB specification) + * @param index index (value between 0 and 65535, called {@code wIndex} in the USB specification) */ -public record USBControlTransfer( - USBRequestType requestType, - USBRecipient recipient, +public record UsbControlTransfer( + UsbRequestType requestType, + UsbRecipient recipient, int request, int value, int index diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBDevice.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbDevice.java similarity index 82% rename from java-does-usb/src/main/java/net/codecrete/usb/USBDevice.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbDevice.java index 67837476..786956ba 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBDevice.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbDevice.java @@ -7,6 +7,9 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + import java.io.InputStream; import java.io.OutputStream; import java.util.List; @@ -15,7 +18,7 @@ * USB device. *

* In order to make control requests and transfer data, the device must be - * opened and an interface must be claimed. In the open state, this current + * opened and an interface must be claimed. In the open state, the current * process has exclusive access to the device. *

*

@@ -23,38 +26,38 @@ * closed state. *

*/ -public interface USBDevice { +public interface UsbDevice { /** * USB product ID. * * @return product ID */ - int productId(); + int getProductId(); /** * USB vendor ID. * * @return vendor ID */ - int vendorId(); + int getVendorId(); /** * Product name. * * @return product name or {@code null} if not provided by the device */ - String product(); + String getProduct(); /** - * Manufacturer name + * Manufacturer name. * * @return manufacturer name or {@code null} if not provided by the device */ - String manufacturer(); + String getManufacturer(); /** - * Serial number + * Serial number. *

* Even though this is supposed to be a human-readable string, * some devices are known to provide binary data. @@ -62,42 +65,42 @@ public interface USBDevice { * * @return serial number or {@code null} if not provided by the device */ - String serialNumber(); + String getSerialNumber(); /** * USB device class code ({@code bDeviceClass} from device descriptor). * * @return class code */ - int classCode(); + int getClassCode(); /** * USB device subclass code ({@code bDeviceSubClass} from device descriptor). * * @return subclass code */ - int subclassCode(); + int getSubclassCode(); /** * USB device protocol ({@code bDeviceProtocol} from device descriptor). * * @return protocol code */ - int protocolCode(); + int getProtocolCode(); /** * USB protocol version supported by this device. * * @return version */ - Version usbVersion(); + @NotNull Version getUsbVersion(); /** * Device version (as declared by the manufacturer). * * @return version */ - Version deviceVersion(); + @NotNull Version getDeviceVersion(); /** * Detaches the standard operating-system drivers of this device. @@ -141,7 +144,7 @@ public interface USBDevice { *

* On Linux, this method changes the behavior of {@link #claimInterface(int)}. Standard drivers will no longer be * detached when the interface is claimed. Standard drivers are automatically reattached when the interfaces - * are released, at the lasted when the device is closed. + * are released, at the latest when the device is closed. *

*

* On Windows, this method does nothing. @@ -149,6 +152,18 @@ public interface USBDevice { */ void attachStandardDrivers(); + /** + * Indicates if the device is connected. + *

+ * When a {@link UsbDevice} instance is initially returned by {@link Usb#getDevices()} and related methods, + * it is connected. When the user unplugs the device, the application can still hold on to instance of + * {@link UsbDevice} even though the actual USB device is gone. This method can be used to check if the + * device is still connected. + *

+ * @return {@code true} if the device is connected, {@code false} if it is no longer connected + */ + boolean isConnected(); + /** * Opens the device for communication. */ @@ -159,7 +174,7 @@ public interface USBDevice { * * @return {@code true} if the device is open, {@code false} if it is closed. */ - boolean isOpen(); + boolean isOpened(); /** * Closes the device. @@ -168,27 +183,34 @@ public interface USBDevice { /** * Gets the interfaces of this device. + *

+ * The returned list is sorted by interface number. + *

* * @return a list of USB interfaces */ - List interfaces(); + @NotNull + @Unmodifiable + List getInterfaces(); /** * Gets the interface with the specified number. * * @param interfaceNumber the interface number - * @return the interface, or {@code null} if no interface with the given number exists + * @return the interface + * @exception UsbException if the interface does not exist */ - USBInterface getInterface(int interfaceNumber); + @NotNull UsbInterface getInterface(int interfaceNumber); /** * Gets the endpoint with the specified number. * * @param direction the endpoint direction * @param endpointNumber the endpoint number (between 1 and 127) - * @return the endpoint, or {@code null} if no endpoint with the given direction and number exists + * @return the endpoint + * @exception UsbException if the endpoint does not exist */ - USBEndpoint getEndpoint(USBDirection direction, int endpointNumber); + @NotNull UsbEndpoint getEndpoint(UsbDirection direction, int endpointNumber); /** * Claims the specified interface for exclusive use. @@ -231,16 +253,16 @@ public interface USBDevice { * or the interface of the addressed endpoint must have been claimed. *

* - * @param setup control transfer setup parameters + * @param transfer control transfer setup parameters * @param length maximum length of expected data * @return received data. */ - byte[] controlTransferIn(USBControlTransfer setup, int length); + byte @NotNull [] controlTransferIn(@NotNull UsbControlTransfer transfer, int length); /** * Executes a control transfer request and optionally sends data. *

- * This method blocks until the device has acknowledge the request or an error has occurred. + * This method blocks until the device has acknowledged the request or an error has occurred. *

*

* The control transfer request is sent to endpoint 0. The transfer is expected to either have @@ -253,10 +275,10 @@ public interface USBDevice { * or the interface of the addressed endpoint must have been claimed. *

* - * @param setup control transfer setup parameters + * @param transfer control transfer setup parameters * @param data data to send, or {@code null} if the transfer has no data stage. */ - void controlTransferOut(USBControlTransfer setup, byte[] data); + void controlTransferOut(@NotNull UsbControlTransfer transfer, byte[] data); /** * Sends data to this device. @@ -275,13 +297,13 @@ public interface USBDevice { * @param endpointNumber endpoint number (in the range between 1 and 127) * @param data data to send */ - void transferOut(int endpointNumber, byte[] data); + void transferOut(int endpointNumber, byte @NotNull [] data); /** * Sends data to this device. *

* This method blocks until the data has been sent, the timeout period has expired - * or an error has occurred. If the timeout expires, a {@link USBTimeoutException} is thrown. + * or an error has occurred. If the timeout expires, a {@link UsbTimeoutException} is thrown. *

*

* This method can send data to bulk and interrupt endpoints. @@ -296,13 +318,13 @@ public interface USBDevice { * @param data data to send * @param timeout the timeout period, in milliseconds (0 for no timeout) */ - void transferOut(int endpointNumber, byte[] data, int timeout); + void transferOut(int endpointNumber, byte @NotNull [] data, int timeout); /** * Sends data to this device. *

* This method blocks until the data has been sent, the timeout period has expired - * or an error has occurred. If the timeout expires, a {@link USBTimeoutException} is thrown. + * or an error has occurred. If the timeout expires, a {@link UsbTimeoutException} is thrown. *

*

* This method can send data to bulk and interrupt endpoints. @@ -319,7 +341,7 @@ public interface USBDevice { * @param length number of bytes to send * @param timeout the timeout period, in milliseconds (0 for no timeout) */ - void transferOut(int endpointNumber, byte[] data, int offset, int length, int timeout); + void transferOut(int endpointNumber, byte @NotNull [] data, int offset, int length, int timeout); /** * Receives data from this device. @@ -337,13 +359,13 @@ public interface USBDevice { * @param endpointNumber endpoint number (in the range between 1 and 127, i.e. without the direction bit) * @return received data */ - byte[] transferIn(int endpointNumber); + byte @NotNull [] transferIn(int endpointNumber); /** * Receives data from this device. *

* This method blocks until at least a packet has been received, the timeout period has expired - * or an error has occurred. If the timeout expired, a {@link USBTimeoutException} is thrown. + * or an error has occurred. If the timeout expired, a {@link UsbTimeoutException} is thrown. *

*

* The returned data is the payload of a packet. It can have a length of 0 if the USB device @@ -357,7 +379,7 @@ public interface USBDevice { * @param timeout the timeout period, in milliseconds (0 for no timeout) * @return received data */ - byte[] transferIn(int endpointNumber, int timeout); + byte @NotNull [] transferIn(int endpointNumber, int timeout); /** * Opens a new output stream to send data to a bulk endpoint. @@ -370,7 +392,7 @@ public interface USBDevice { * and the last packet size was equal to maximum packet size of the endpoint. *

*

- * If {@link #transferOut(int, byte[])} and a output stream or multiple output streams + * If {@link #transferOut(int, byte[])} and an output stream or multiple output streams * are used concurrently for the same endpoint, the behavior is unpredictable. *

* @@ -378,7 +400,7 @@ public interface USBDevice { * @param bufferSize approximate buffer size (in bytes) * @return the new output stream */ - OutputStream openOutputStream(int endpointNumber, int bufferSize); + @NotNull OutputStream openOutputStream(int endpointNumber, int bufferSize); /** * Opens a new output stream to send data to a bulk endpoint. @@ -389,7 +411,7 @@ public interface USBDevice { * @param endpointNumber bulk endpoint number (in the range between 1 and 127) * @return the new output stream */ - default OutputStream openOutputStream(int endpointNumber) { + default @NotNull OutputStream openOutputStream(int endpointNumber) { return openOutputStream(endpointNumber, 1); } @@ -409,7 +431,7 @@ default OutputStream openOutputStream(int endpointNumber) { * @param bufferSize approximate buffer size (in bytes) * @return the new input stream */ - InputStream openInputStream(int endpointNumber, int bufferSize); + @NotNull InputStream openInputStream(int endpointNumber, int bufferSize); /** * Opens a new input stream to receive data from a bulk endpoint. @@ -421,7 +443,7 @@ default OutputStream openOutputStream(int endpointNumber) { * @param endpointNumber bulk endpoint number (in the range between 1 and 127, i.e. without the direction bit) * @return the new input stream */ - default InputStream openInputStream(int endpointNumber) { + default @NotNull InputStream openInputStream(int endpointNumber) { return openInputStream(endpointNumber, 1); } @@ -434,7 +456,7 @@ default InputStream openInputStream(int endpointNumber) { * @param direction endpoint direction * @param endpointNumber endpoint number (in the range between 1 and 127) */ - void abortTransfers(USBDirection direction, int endpointNumber); + void abortTransfers(UsbDirection direction, int endpointNumber); /** * Clears an endpoint's halt condition. @@ -450,19 +472,19 @@ default InputStream openInputStream(int endpointNumber) { * @param direction endpoint direction * @param endpointNumber endpoint number (in the range between 1 and 127) */ - void clearHalt(USBDirection direction, int endpointNumber); + void clearHalt(UsbDirection direction, int endpointNumber); /** * Gets the device descriptor. * * @return the device descriptor (as a byte array) */ - byte[] deviceDescriptor(); + byte @NotNull [] getDeviceDescriptor(); /** * Gets the configuration descriptor. * * @return the configuration descriptor (as a byte array) */ - byte[] configurationDescriptor(); + byte @NotNull [] getConfigurationDescriptor(); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBDevicePredicate.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbDevicePredicate.java similarity index 65% rename from java-does-usb/src/main/java/net/codecrete/usb/USBDevicePredicate.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbDevicePredicate.java index 6b1b773b..687db9ed 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBDevicePredicate.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbDevicePredicate.java @@ -7,32 +7,34 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; + import java.util.List; /** * Represents a predicate (boolean-valued function) of one argument, evaluated for a given USB device. *

- * This is a functional interface whose functional method is {@link #matches(USBDevice)}. + * This is a functional interface whose functional method is {@link #matches(UsbDevice)}. *

*/ @FunctionalInterface -public interface USBDevicePredicate { +public interface UsbDevicePredicate { /** * Evaluates this predicate on the given USB device. * * @param device the USB device - * @return {@code true} of the devices matches the predicate, otherwise {@code false} + * @return {@code true} if the device matches the predicate, otherwise {@code false} */ - boolean matches(USBDevice device); + boolean matches(@NotNull UsbDevice device); /** - * Test if the USB devices matches any of the filter conditions. + * Tests whether the USB device matches any of the filter conditions. * * @param device the USB device * @param predicates a list of filter predicates * @return {@code true} if it matches, {@code false} otherwise */ - static boolean matchesAny(USBDevice device, List predicates) { + static boolean matchesAny(@NotNull UsbDevice device, @NotNull List predicates) { return predicates.stream().anyMatch(predicate -> predicate.matches(device)); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBDirection.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbDirection.java similarity index 92% rename from java-does-usb/src/main/java/net/codecrete/usb/USBDirection.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbDirection.java index 8e2e7981..8e561dc4 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBDirection.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbDirection.java @@ -10,7 +10,7 @@ /** * USB endpoint data direction enumeration. */ -public enum USBDirection { +public enum UsbDirection { /** * Direction OUT (host to device) */ diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBEndpoint.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbEndpoint.java similarity index 87% rename from java-does-usb/src/main/java/net/codecrete/usb/USBEndpoint.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbEndpoint.java index 434e0d34..1cebc06b 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBEndpoint.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbEndpoint.java @@ -13,7 +13,7 @@ * Instances of this class describe a USB endpoint. *

*/ -public interface USBEndpoint { +public interface UsbEndpoint { /** * Gets the USB endpoint number. @@ -24,12 +24,12 @@ public interface USBEndpoint { *

*

* Use this number when calling any of the transfer methods of a - * {@link USBDevice} instance. + * {@link UsbDevice} instance. *

* * @return the endpoint number */ - int number(); + int getNumber(); /** * Gets the direction of the endpoint. @@ -40,14 +40,14 @@ public interface USBEndpoint { * * @return the direction */ - USBDirection direction(); + UsbDirection getDirection(); /** * Gets the USB endpoint transfer type. * * @return the transfer type */ - USBTransferType transferType(); + UsbTransferType getTransferType(); /** * Gets the packet size. @@ -58,5 +58,5 @@ public interface USBEndpoint { * * @return the packet size, in bytes. */ - int packetSize(); + int getPacketSize(); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBException.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbException.java similarity index 74% rename from java-does-usb/src/main/java/net/codecrete/usb/USBException.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbException.java index dacc902a..e0c62acb 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbException.java @@ -7,10 +7,13 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + /** * USB exception, thrown if an operation with USB devices fails. */ -public class USBException extends RuntimeException { +public class UsbException extends RuntimeException { /** * Error code. @@ -22,7 +25,7 @@ public class USBException extends RuntimeException { * * @param message the message */ - public USBException(String message) { + public UsbException(@NotNull String message) { super(message); code = -1; } @@ -33,7 +36,7 @@ public USBException(String message) { * @param message the message * @param errorCode the error code */ - public USBException(String message, int errorCode) { + public UsbException(@NotNull String message, int errorCode) { super(message + " (error code: " + errorCode + ")"); code = errorCode; } @@ -44,7 +47,7 @@ public USBException(String message, int errorCode) { * @param message the message * @param cause the causal exception */ - public USBException(String message, Throwable cause) { + public UsbException(@NotNull String message, @Nullable Throwable cause) { super(message, cause); code = -1; } @@ -54,7 +57,7 @@ public USBException(String message, Throwable cause) { * * @return the error code */ - public int errorCode() { + public int getErrorCode() { return code; } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBInterface.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbInterface.java similarity index 58% rename from java-does-usb/src/main/java/net/codecrete/usb/USBInterface.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbInterface.java index 8f63c649..67fde72f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBInterface.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbInterface.java @@ -7,6 +7,9 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + import java.util.List; /** @@ -15,7 +18,7 @@ * Instances of this class describe an interface of a USB device. *

*/ -public interface USBInterface { +public interface UsbInterface { /** * Gets the interface number. @@ -25,10 +28,10 @@ public interface USBInterface { * * @return the interface number */ - int number(); + int getNumber(); /** - * Indicates if this interface is currently claimed for exclusive access. + * Indicates if this interface has been claimed by this program for exclusive access. * * @return {@code true} if it is claimed, {@code false} otherwise. */ @@ -37,25 +40,31 @@ public interface USBInterface { /** * Gets the currently selected alternate interface setting. *

- * Initially, the alternate settings with number 0 is selected. + * Initially, the alternate setting with number 0 is selected. *

* * @return the alternate interface setting. */ - USBAlternateInterface alternate(); + @NotNull UsbAlternateInterface getCurrentAlternate(); /** - * Gets the alternate interface settings with the specified number. + * Gets the alternate interface setting with the specified number. * * @param alternateNumber alternate setting number * @return alternate interface setting + * @throws UsbException if the alternate setting does not exist */ - USBAlternateInterface getAlternate(int alternateNumber); + @NotNull UsbAlternateInterface getAlternate(int alternateNumber); /** * Gets all alternate settings of this interface. + *

+ * The returned list is sorted by alternate setting number. + *

* * @return a list of the alternate settings */ - List alternates(); + @NotNull + @Unmodifiable + List getAlternates(); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBRecipient.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbRecipient.java similarity index 93% rename from java-does-usb/src/main/java/net/codecrete/usb/USBRecipient.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbRecipient.java index 250238a2..756027a2 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBRecipient.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbRecipient.java @@ -10,7 +10,7 @@ /** * USB control transfer recipient enumeration. */ -public enum USBRecipient { +public enum UsbRecipient { /** * USB device */ diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBRequestType.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbRequestType.java similarity index 93% rename from java-does-usb/src/main/java/net/codecrete/usb/USBRequestType.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbRequestType.java index 05ede7e6..08dec0d6 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBRequestType.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbRequestType.java @@ -10,7 +10,7 @@ /** * USB control transfer request type enumeration. */ -public enum USBRequestType { +public enum UsbRequestType { /** * Standard request type */ diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBStallException.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbStallException.java similarity index 54% rename from java-does-usb/src/main/java/net/codecrete/usb/USBStallException.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbStallException.java index 2b986a23..e60da595 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBStallException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbStallException.java @@ -7,24 +7,26 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; + /** - * Exception thrown if a communication on a USB endpoint failed. + * Exception thrown if communication on a USB endpoint fails. *

* If a USB endpoint stalls, it is halted and the halt condition must be cleared - * using {@link USBDevice#clearHalt(USBDirection, int)} before communication can resume. + * using {@link UsbDevice#clearHalt(UsbDirection, int)} before communication can resume. *

*

- * If the control endpoint 0 stalls, it throws this exception but is not halted. + * If the control endpoint 0 stalls, this exception is thrown but the endpoint is not halted. *

*/ -public class USBStallException extends USBException { +public class UsbStallException extends UsbException { /** * Creates a new instance with a message. * * @param message the message */ - public USBStallException(String message) { + public UsbStallException(@NotNull String message) { super(message); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBTimeoutException.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbTimeoutException.java similarity index 69% rename from java-does-usb/src/main/java/net/codecrete/usb/USBTimeoutException.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbTimeoutException.java index 3b18558f..28ae2f72 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBTimeoutException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbTimeoutException.java @@ -7,17 +7,19 @@ package net.codecrete.usb; +import org.jetbrains.annotations.NotNull; + /** * Exception thrown if a USB operation times out. */ -public class USBTimeoutException extends USBException { +public class UsbTimeoutException extends UsbException { /** * Creates a new instance with a message. * * @param message the message */ - public USBTimeoutException(String message) { + public UsbTimeoutException(@NotNull String message) { super(message); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/USBTransferType.java b/java-does-usb/src/main/java/net/codecrete/usb/UsbTransferType.java similarity index 93% rename from java-does-usb/src/main/java/net/codecrete/usb/USBTransferType.java rename to java-does-usb/src/main/java/net/codecrete/usb/UsbTransferType.java index bfeaa0c0..f08a2e40 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/USBTransferType.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/UsbTransferType.java @@ -10,7 +10,7 @@ /** * USB endpoint transfer type enumeration. */ -public enum USBTransferType { +public enum UsbTransferType { /** * Control transfer */ diff --git a/java-does-usb/src/main/java/net/codecrete/usb/Version.java b/java-does-usb/src/main/java/net/codecrete/usb/Version.java index 106d7b74..90b507f5 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/Version.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/Version.java @@ -19,7 +19,7 @@ public final class Version { *

* {@code bcdVersion} contains the version: the high byte is the major * version. The low byte is split into two nibbles (4 bits), the high one - * is minor version, the low one is the subminor version. As an example, + * is the minor version, the low one is the subminor version. As an example, * 0x0321 represents the version 3.2.1. *

* @@ -34,7 +34,7 @@ public Version(int bcdVersion) { * * @return major version */ - public int major() { + public int getMajor() { return bcdVersion >> 8; } @@ -43,7 +43,7 @@ public int major() { * * @return minor version */ - public int minor() { + public int getMinor() { return (bcdVersion >> 4) & 0x0f; } @@ -52,13 +52,13 @@ public int minor() { * * @return subminor version */ - public int subminor() { + public int getSubminor() { return bcdVersion & 0x0f; } @Override public String toString() { - return String.format("%d.%d.%d", major(), minor(), subminor()); + return String.format("%d.%d.%d", getMajor(), getMinor(), getSubminor()); } @Override diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/CompositeFunction.java b/java-does-usb/src/main/java/net/codecrete/usb/common/CompositeFunction.java index 049bbdc6..b6e751a4 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/CompositeFunction.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/CompositeFunction.java @@ -45,14 +45,31 @@ public CompositeFunction(int firstInterfaceNumber, int numInterfaces, int classC functionProtocol = protocolCode; } + /** + * Gets the number of the first interface contained in this function. + * @return the interface number + */ public int firstInterfaceNumber() { return firstIntfNumber; } + /** + * Gets the number of interfaces contained in this function. + * @return the number of interfaces + */ public int numInterfaces() { return interfaceCount; } + /** + * Indicates if this function contains the specified interface. + * @param interfaceNumber the interface number + * @return {@code true} if it is contained, {@code false} otherwise + */ + public boolean containsInterface(int interfaceNumber) { + return interfaceNumber >= firstIntfNumber && interfaceNumber < firstIntfNumber + interfaceCount; + } + public int classCode() { return functionCode; } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/Configuration.java b/java-does-usb/src/main/java/net/codecrete/usb/common/Configuration.java index e1ad6992..dc5317d1 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/Configuration.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/Configuration.java @@ -7,7 +7,7 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBInterface; +import net.codecrete.usb.UsbInterface; import java.util.ArrayList; import java.util.List; @@ -17,7 +17,7 @@ */ public class Configuration { private final List functionList; - private final List interfaceList; + private final List interfaceList; private final int configurationValue; private final int configurationAttributes; private final int configurationMaxPower; @@ -42,7 +42,7 @@ public int maxPower() { return configurationMaxPower; } - public List interfaces() { + public List interfaces() { return interfaceList; } @@ -50,12 +50,13 @@ public List functions() { return functionList; } - public void addInterface(USBInterface intf) { + public void addInterface(UsbInterface intf) { interfaceList.add(intf); } - public USBInterfaceImpl findInterfaceByNumber(int number) { - return (USBInterfaceImpl) interfaceList.stream().filter(intf -> intf.number() == number).findFirst().orElse(null); + public UsbInterfaceImpl findInterfaceByNumber(int number) { + return (UsbInterfaceImpl) interfaceList.stream().filter(intf -> intf.getNumber() == number) + .findFirst().orElse(null); } public void addFunction(CompositeFunction function) { @@ -63,6 +64,7 @@ public void addFunction(CompositeFunction function) { } public CompositeFunction findFunction(int interfaceNumber) { - return functionList.stream().filter(f -> interfaceNumber >= f.firstInterfaceNumber() && interfaceNumber < f.firstInterfaceNumber() + f.numInterfaces()).findFirst().orElse(null); + return functionList.stream().filter(f -> f.containsInterface(interfaceNumber)) + .findFirst().orElse(null); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/ConfigurationParser.java b/java-does-usb/src/main/java/net/codecrete/usb/common/ConfigurationParser.java index 16c989cd..f8023292 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/ConfigurationParser.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/ConfigurationParser.java @@ -7,10 +7,10 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBAlternateInterface; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBException; -import net.codecrete.usb.USBTransferType; +import net.codecrete.usb.UsbAlternateInterface; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbTransferType; import net.codecrete.usb.usbstandard.ConfigurationDescriptor; import net.codecrete.usb.usbstandard.EndpointDescriptor; import net.codecrete.usb.usbstandard.InterfaceAssociationDescriptor; @@ -20,10 +20,18 @@ import java.lang.foreign.ValueLayout; import java.util.ArrayList; -import static net.codecrete.usb.usbstandard.Constants.*; +import static net.codecrete.usb.usbstandard.Constants.CONFIGURATION_DESCRIPTOR_TYPE; +import static net.codecrete.usb.usbstandard.Constants.ENDPOINT_DESCRIPTOR_TYPE; +import static net.codecrete.usb.usbstandard.Constants.INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE; +import static net.codecrete.usb.usbstandard.Constants.INTERFACE_DESCRIPTOR_TYPE; /** - * Parser for USB configuration descriptors + * Parser for USB configuration descriptors. + * + *

+ * It extracts the information about endpoints, interfaces (incl. alternate interfaces) and associations + * between interfaces to derive the functions. Other descriptor types are ignored. + *

*/ public class ConfigurationParser { @@ -53,7 +61,7 @@ public ConfigurationParser(MemorySegment descriptor) { public Configuration parse() { parseHeader(); - USBAlternateInterfaceImpl lastAlternate = null; + UsbAlternateInterfaceImpl lastAlternate = null; var offset = peekDescLength(0); while (offset < descriptor.byteSize()) { @@ -64,18 +72,18 @@ public Configuration parse() { if (descType == INTERFACE_DESCRIPTOR_TYPE) { var intf = parseInterface(offset); - var parent = configuration.findInterfaceByNumber(intf.number()); + var parent = configuration.findInterfaceByNumber(intf.getNumber()); if (parent != null) { - parent.addAlternate(intf.alternate()); + parent.addAlternate(intf.getCurrentAlternate()); } else { configuration.addInterface(intf); } - lastAlternate = (USBAlternateInterfaceImpl) intf.alternate(); + lastAlternate = (UsbAlternateInterfaceImpl) intf.getCurrentAlternate(); - var function = configuration.findFunction(intf.number()); + var function = configuration.findFunction(intf.getNumber()); if (function == null) { - function = new CompositeFunction(intf.number(), 1, lastAlternate.classCode(), - lastAlternate.subclassCode(), lastAlternate.protocolCode()); + function = new CompositeFunction(intf.getNumber(), 1, lastAlternate.getClassCode(), + lastAlternate.getSubclassCode(), lastAlternate.getProtocolCode()); configuration.addFunction(function); } @@ -97,22 +105,22 @@ public Configuration parse() { private void parseHeader() { var desc = new ConfigurationDescriptor(descriptor); if (CONFIGURATION_DESCRIPTOR_TYPE != desc.descriptorType()) - throw new USBException("invalid USB configuration descriptor"); + throw new UsbException("invalid USB configuration descriptor"); var totalLength = desc.totalLength(); if (descriptor.byteSize() != totalLength) - throw new USBException("invalid USB configuration descriptor (invalid length)"); + throw new UsbException("invalid USB configuration descriptor (invalid length)"); configuration = new Configuration(desc.configurationValue(), desc.attributes(), desc.maxPower()); } - private USBInterfaceImpl parseInterface(int offset) { + private UsbInterfaceImpl parseInterface(int offset) { var desc = new InterfaceDescriptor(descriptor, offset); - var alternate = new USBAlternateInterfaceImpl(desc.alternateSetting(), desc.interfaceClass(), + var alternate = new UsbAlternateInterfaceImpl(desc.alternateSetting(), desc.interfaceClass(), desc.interfaceSubClass(), desc.interfaceProtocol(), new ArrayList<>()); - var alternates = new ArrayList(); + var alternates = new ArrayList(); alternates.add(alternate); - return new USBInterfaceImpl(desc.interfaceNumber(), alternates); + return new UsbInterfaceImpl(desc.interfaceNumber(), alternates); } private void parseIAD(int offset) { @@ -122,26 +130,26 @@ private void parseIAD(int offset) { configuration.addFunction(function); } - private USBEndpointImpl parseEndpoint(int offset) { + private UsbEndpointImpl parseEndpoint(int offset) { var desc = new EndpointDescriptor(descriptor, offset); var address = desc.endpointAddress(); - return new USBEndpointImpl(getEndpointNumber(address), getEndpointDirection(address), + return new UsbEndpointImpl(getEndpointNumber(address), getEndpointDirection(address), getEndpointType(desc.attributes()), desc.maxPacketSize()); } - private static USBDirection getEndpointDirection(int address) { - return (address & 0x80) != 0 ? USBDirection.IN : USBDirection.OUT; + private static UsbDirection getEndpointDirection(int address) { + return (address & 0x80) != 0 ? UsbDirection.IN : UsbDirection.OUT; } private static int getEndpointNumber(int address) { return address & 0x7f; } - private static USBTransferType getEndpointType(int attributes) { + private static UsbTransferType getEndpointType(int attributes) { return switch (attributes & 0x3) { - case 1 -> USBTransferType.ISOCHRONOUS; - case 2 -> USBTransferType.BULK; - case 3 -> USBTransferType.INTERRUPT; + case 1 -> UsbTransferType.ISOCHRONOUS; + case 2 -> UsbTransferType.BULK; + case 3 -> UsbTransferType.INTERRUPT; default -> null; }; } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointInputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointInputStream.java index 7e00f1fb..167b041c 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointInputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointInputStream.java @@ -7,15 +7,21 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBException; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.InputStream; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.util.Objects; import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; +import static net.codecrete.usb.common.EndpointStreams.toIOException; + +import static java.lang.System.Logger.Level.WARNING; import static java.lang.foreign.ValueLayout.JAVA_BYTE; /** @@ -35,7 +41,14 @@ */ public abstract class EndpointInputStream extends InputStream { - protected USBDeviceImpl device; + private static final System.Logger LOG = System.getLogger(EndpointInputStream.class.getName()); + + // Maximum time (ms) to wait for outstanding transfers to complete during teardown. + // A completion that is never delivered (e.g. after an unplug) then degrades to a + // logged warning instead of a permanent hang. + private static final long TEARDOWN_TIMEOUT_MS = 1000; + + protected UsbDeviceImpl device; protected final int endpointNumber; // Arena to allocate buffers and completion handlers protected final Arena arena; @@ -58,16 +71,17 @@ public abstract class EndpointInputStream extends InputStream { * @param endpointNumber endpoint number * @param bufferSize approximate buffer size (in bytes) */ - protected EndpointInputStream(USBDeviceImpl device, int endpointNumber, int bufferSize) { + protected EndpointInputStream(UsbDeviceImpl device, int endpointNumber, int bufferSize) { this.device = device; this.endpointNumber = endpointNumber; - arena = Arena.ofShared(); + //arena = Arena.ofShared(); // not supported by GraalVM + arena = Arena.ofAuto(); - var packetSize = device.getEndpoint(USBDirection.IN, endpointNumber).packetSize(); + var packetSize = device.getEndpoint(UsbDirection.IN, endpointNumber).getPacketSize(); // use between 4 and 32 packets per transfer (256B to 2KB for FS, 2KB to 16KB for HS) var numPacketsPerTransfer = (int) Math.round(Math.sqrt((double) bufferSize / packetSize)); - numPacketsPerTransfer = Math.min(Math.max(numPacketsPerTransfer, 4), 32); + numPacketsPerTransfer = Math.clamp(numPacketsPerTransfer, 4, 32); transferSize = numPacketsPerTransfer * packetSize; // use at least 2 outstanding transfers (3 in total) @@ -109,9 +123,9 @@ public void close() throws IOException { // abort all transfers on endpoint try { - device.abortTransfers(USBDirection.IN, endpointNumber); + device.abortTransfers(UsbDirection.IN, endpointNumber); - } catch (USBException e) { + } catch (UsbException _) { // If aborting the transfer is not possible, the device has // likely been closed or unplugged. So all outstanding // transfers will terminate anyway. @@ -123,44 +137,66 @@ public void close() throws IOException { @Override public int read() throws IOException { - if (isClosed()) - return -1; + ensureOpen(); - if (available() == 0) - receiveMoreData(); + try { + if (bufferedBytes() == 0) + receiveMoreData(); - var b = currentTransfer.data().get(JAVA_BYTE, readOffset) & 0xff; - readOffset += 1; - return b; + var b = currentTransfer.data().get(JAVA_BYTE, readOffset) & 0xff; + readOffset += 1; + return b; + + } catch (UsbException e) { + throw toIOException(e); + } } @Override - public int read(byte[] b, int off, int len) throws IOException { - if (isClosed()) - return -1; + public int read(byte @NotNull [] b, int off, int len) throws IOException { + Objects.checkFromIndexSize(off, len, b.length); + ensureOpen(); + if (len == 0) + return 0; - var numRead = 0; - do { - if (available() == 0) - receiveMoreData(); + try { + var numRead = 0; + do { + if (bufferedBytes() == 0) + receiveMoreData(); - // copy data to receiving buffer - var n = Math.min(len - numRead, currentTransfer.resultSize() - readOffset); - MemorySegment.copy(currentTransfer.data(), readOffset, MemorySegment.ofArray(b), (long) off + numRead, n); - readOffset += n; - numRead += n; + // copy data to receiving buffer + var n = Math.min(len - numRead, currentTransfer.resultSize() - readOffset); + MemorySegment.copy(currentTransfer.data(), readOffset, MemorySegment.ofArray(b), (long) off + numRead, n); + readOffset += n; + numRead += n; - } while (numRead < len && hasMoreTransfers()); + } while (numRead < len && hasMoreTransfers()); - return numRead; + return numRead; + + } catch (UsbException e) { + throw toIOException(e); + } } - @SuppressWarnings("RedundantThrows") @Override public int available() throws IOException { + ensureOpen(); + return bufferedBytes(); + } + + // Bytes buffered in the current transfer, without a closed-stream check. + // Callers on the read path guard with ensureOpen() first. + private int bufferedBytes() { return currentTransfer.resultSize() - readOffset; } + private void ensureOpen() throws IOException { + if (isClosed()) + throw new IOException("input stream has been closed"); + } + private boolean hasMoreTransfers() { return !completedTransferQueue.isEmpty(); } @@ -190,14 +226,23 @@ private void receiveMoreData() throws IOException { } private Transfer waitForCompletedTransfer() { - while (true) { - try { - var transfer = completedTransferQueue.take(); - numOutstandingTransfers -= 1; - return transfer; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // inside the loop (which would make the next take() throw immediately and + // busy-spin). Re-assert once the completion has actually arrived. + var wasInterrupted = false; + try { + while (true) { + try { + var transfer = completedTransferQueue.take(); + numOutstandingTransfers -= 1; + return transfer; + } catch (InterruptedException _) { + wasInterrupted = true; + } } + } finally { + if (wasInterrupted) + Thread.currentThread().interrupt(); } } @@ -210,14 +255,40 @@ private void onCompletion(Transfer transfer) { completedTransferQueue.add(transfer); } + @SuppressWarnings("java:S2142") private void collectOutstandingTransfers() { - // wait until completion handlers have been called - while (numOutstandingTransfers > 0) - waitForCompletedTransfer(); + // Wait until the completion handlers have been called. This is a teardown path, + // so the wait is bounded: if a completion is never delivered (device unplugged, + // or the completion is lost in a source-removal race), abandon the transfer and + // log a warning instead of blocking the application thread forever. + var deadline = System.currentTimeMillis() + TEARDOWN_TIMEOUT_MS; + var wasInterrupted = false; + + while (numOutstandingTransfers > 0) { + var remaining = deadline - System.currentTimeMillis(); + if (remaining <= 0) { + LOG.log(WARNING, + "abandoning {0} outstanding transfer(s) during input stream teardown - no completion within {1} ms", + numOutstandingTransfers, TEARDOWN_TIMEOUT_MS); + break; + } + + try { + if (completedTransferQueue.poll(remaining, TimeUnit.MILLISECONDS) != null) + numOutstandingTransfers -= 1; + } catch (InterruptedException _) { + // defer the interrupt: keep polling the remaining time without re-setting + // the flag (avoids a busy-spin), then re-assert it once we are done + wasInterrupted = true; + } + } + + if (wasInterrupted) + Thread.currentThread().interrupt(); completedTransferQueue.clear(); currentTransfer = null; - arena.close(); + //arena.close(); } protected abstract void submitTransferIn(Transfer transfer); diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointOutputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointOutputStream.java index 0a8c7f82..c371939e 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointOutputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointOutputStream.java @@ -7,15 +7,22 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBDirection; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.OutputStream; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.util.Arrays; +import java.util.Objects; import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; +import static net.codecrete.usb.common.EndpointStreams.toIOException; + +import static java.lang.System.Logger.Level.WARNING; import static java.lang.foreign.ValueLayout.JAVA_BYTE; /** @@ -37,7 +44,14 @@ */ public abstract class EndpointOutputStream extends OutputStream { - protected USBDeviceImpl device; + private static final System.Logger LOG = System.getLogger(EndpointOutputStream.class.getName()); + + // Maximum time (ms) to wait for outstanding transfers to complete during teardown. + // A completion that is never delivered (e.g. after an unplug) then degrades to a + // logged warning instead of a permanent hang. + private static final long TEARDOWN_TIMEOUT_MS = 1000; + + protected UsbDeviceImpl device; protected final int endpointNumber; protected final Arena arena; // Endpoint packet size @@ -60,16 +74,17 @@ public abstract class EndpointOutputStream extends OutputStream { * @param endpointNumber endpoint number * @param bufferSize approximate buffer size (in bytes) */ - protected EndpointOutputStream(USBDeviceImpl device, int endpointNumber, int bufferSize) { + protected EndpointOutputStream(UsbDeviceImpl device, int endpointNumber, int bufferSize) { this.device = device; this.endpointNumber = endpointNumber; - arena = Arena.ofShared(); + //arena = Arena.ofShared(); // not supported by GraalVM + arena = Arena.ofAuto(); - packetSize = device.getEndpoint(USBDirection.OUT, endpointNumber).packetSize(); + packetSize = device.getEndpoint(UsbDirection.OUT, endpointNumber).getPacketSize(); // use between 4 and 32 packets per transfer (256B to 2KB for FS, 2KB to 16KB for HS) var numPacketsPerTransfer = (int) Math.round(Math.sqrt((double) bufferSize / packetSize)); - numPacketsPerTransfer = Math.min(Math.max(numPacketsPerTransfer, 4), 32); + numPacketsPerTransfer = Math.clamp(numPacketsPerTransfer, 4, 32); transferSize = numPacketsPerTransfer * packetSize; // use at least 2 outstanding transfers (3 in total) @@ -102,54 +117,183 @@ public void close() throws IOException { if (isClosed()) return; - if (!hasError) - flush(); - else - waitForOutstandingTransfers(); + // Teardown path: every wait is bounded by a single deadline so a lost completion + // (device unplugged, or completion dropped in a source-removal race) degrades to a + // logged warning instead of hanging the application thread. Unlike the public + // flush(), this must not route through the unbounded waits. + var deadline = System.currentTimeMillis() + TEARDOWN_TIMEOUT_MS; + + try { + if (!hasError) { + // best-effort: transmit any remaining buffered data (and a ZLP if needed) + if (writeOffset > 0) + submitForClose(writeOffset, deadline); + if (needsZlp && currentTransfer != null) + submitForClose(0, deadline); + } + + drainOutstandingTransfers(deadline); + + } catch (Exception e) { + // teardown must not fail; data-path errors are already surfaced by write()/flush() + LOG.log(WARNING, "error while closing output stream - ignoring", e); + + } finally { + device = null; + availableTransferQueue.clear(); + currentTransfer = null; + //arena.close(); + } + } + + /** + * Submits the current transfer during teardown and acquires a replacement, + * both bounded by the given deadline. + *

+ * Unlike {@link #submitTransfer(int)} this does not recurse into {@link #close()} on error, + * and it does not block indefinitely when acquiring the next transfer instance. + *

+ * + * @param size size of data to be transmitted + * @param deadline absolute deadline (ms since epoch) for acquiring the next transfer + */ + private void submitForClose(int size, long deadline) { + currentTransfer.setDataSize(size); + submitTransferOut(currentTransfer); + + synchronized (this) { + numOutstandingTransfers += 1; + } - device = null; - availableTransferQueue.clear(); - currentTransfer = null; - arena.close(); + needsZlp = size == packetSize; + writeOffset = 0; + // if no transfer becomes available within the deadline, currentTransfer stays null, + // the drain below still bounded-waits for the in-flight transfer to complete + currentTransfer = pollAvailableTransfer(deadline); + } + + /** + * Waits for all outstanding transfers to complete, bounded by the given deadline. + *

+ * If a completion is not delivered in time, the remaining transfers are abandoned and a + * warning is logged. + *

+ * + * @param deadline absolute deadline (ms since epoch) + */ + private void drainOutstandingTransfers(long deadline) { + int numTransfers; + synchronized (this) { + numTransfers = numOutstandingTransfers + availableTransferQueue.size(); + } + + for (var i = 0; i < numTransfers; i++) { + if (pollAvailableTransfer(deadline) == null) { + int abandoned; + synchronized (this) { + abandoned = numOutstandingTransfers; + } + LOG.log(WARNING, + "abandoning {0} outstanding transfer(s) during output stream teardown - no completion within {1} ms", + abandoned, TEARDOWN_TIMEOUT_MS); + break; + } + } + } + + /** + * Waits until a transfer instance is available for use, bounded by the given deadline. + * + * @param deadline absolute deadline (ms since epoch) + * @return transfer instance ready for use, or {@code null} if the deadline expired + */ + private Transfer pollAvailableTransfer(long deadline) { + var wasInterrupted = false; + try { + while (true) { + var remaining = deadline - System.currentTimeMillis(); + if (remaining <= 0) + return null; + + try { + var transfer = availableTransferQueue.poll(remaining, TimeUnit.MILLISECONDS); + if (transfer == null) + return null; + + // surface a transfer error unless we are already in the error path + var result = transfer.resultCode(); + if (result != 0 && !hasError) { + transfer.setResultCode(0); + device.throwOSException(result, "error occurred while transmitting to endpoint %d", endpointNumber); + } + + return transfer; + + } catch (InterruptedException _) { + // defer the interrupt: keep polling the remaining time without re-setting + // the flag (avoids a busy-spin), then re-assert it once we are done + wasInterrupted = true; + } + } + } finally { + if (wasInterrupted) + Thread.currentThread().interrupt(); + } } @Override public void write(int b) throws IOException { - checkIsOpen(); + ensureOpen(); + + try { + currentTransfer.data().set(JAVA_BYTE, writeOffset, (byte) b); + writeOffset += 1; + if (writeOffset == transferSize) + submitTransfer(writeOffset); - currentTransfer.data().set(JAVA_BYTE, writeOffset, (byte) b); - writeOffset += 1; - if (writeOffset == transferSize) - submitTransfer(writeOffset); + } catch (UsbException e) { + throw toIOException(e); + } } @Override - public void write(byte[] b, int off, int len) throws IOException { - checkIsOpen(); + public void write(byte @NotNull [] b, int off, int len) throws IOException { + Objects.checkFromIndexSize(off, len, b.length); + ensureOpen(); - while (len > 0) { - var chunkSize = Math.min(len, transferSize - writeOffset); - MemorySegment.copy(b, off, currentTransfer.data(), JAVA_BYTE, writeOffset, chunkSize); - writeOffset += chunkSize; - off += chunkSize; - len -= chunkSize; + try { + while (len > 0) { + var chunkSize = Math.min(len, transferSize - writeOffset); + MemorySegment.copy(b, off, currentTransfer.data(), JAVA_BYTE, writeOffset, chunkSize); + writeOffset += chunkSize; + off += chunkSize; + len -= chunkSize; + + if (writeOffset == transferSize) + submitTransfer(writeOffset); + } - if (writeOffset == transferSize) - submitTransfer(writeOffset); + } catch (UsbException e) { + throw toIOException(e); } } @Override public void flush() throws IOException { - checkIsOpen(); + ensureOpen(); + + try { + if (writeOffset > 0) + submitTransfer(writeOffset); - if (writeOffset > 0) - submitTransfer(writeOffset); + if (needsZlp) + submitTransfer(0); - if (needsZlp) - submitTransfer(0); + waitForOutstandingTransfers(); - waitForOutstandingTransfers(); + } catch (UsbException e) { + throw toIOException(e); + } } /** @@ -220,22 +364,31 @@ private void waitForOutstandingTransfers() { * @return transfer instance ready for use */ private Transfer waitForAvailableTransfer() { - while (true) { - try { - var transfer = availableTransferQueue.take(); - - // check for error - var result = transfer.resultCode(); - if (result != 0 && !hasError) { - transfer.setResultCode(0); - device.throwOSException(result, "error occurred while transmitting to endpoint %d", endpointNumber); - } + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // inside the loop (which would make the next take() throw immediately and + // busy-spin). Re-assert once a transfer has actually become available. + var wasInterrupted = false; + try { + while (true) { + try { + var transfer = availableTransferQueue.take(); - return transfer; + // check for error + var result = transfer.resultCode(); + if (result != 0 && !hasError) { + transfer.setResultCode(0); + device.throwOSException(result, "error occurred while transmitting to endpoint %d", endpointNumber); + } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + return transfer; + + } catch (InterruptedException _) { + wasInterrupted = true; + } } + } finally { + if (wasInterrupted) + Thread.currentThread().interrupt(); } } @@ -254,8 +407,8 @@ private synchronized void onCompletion(Transfer transfer) { protected void configureEndpoint() { } - private void checkIsOpen() throws IOException { + private void ensureOpen() throws IOException { if (isClosed()) - throw new IOException("endpoint output stream has been closed"); + throw new IOException("output stream has been closed"); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointStreams.java b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointStreams.java new file mode 100644 index 00000000..5e9fda43 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/EndpointStreams.java @@ -0,0 +1,44 @@ +// +// Java Does USB +// Copyright (c) 2023 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.common; + +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbTimeoutException; + +import java.io.IOException; +import java.io.InterruptedIOException; + +/** + * Helpers shared by {@link EndpointInputStream} and {@link EndpointOutputStream}. + */ +final class EndpointStreams { + + private EndpointStreams() { + } + + /** + * Wraps a USB error in an {@link IOException} so it is surfaced through the + * {@link java.io.InputStream}/{@link java.io.OutputStream} contract. + *

+ * A transfer timeout is mapped to {@link InterruptedIOException} (java.io's "I/O timed out"). + * All other USB errors become a plain {@link IOException} with the {@link UsbException} as cause, + * which preserves the USB error code and any stall/timeout subtype for callers that inspect it. + *

+ * + * @param e the USB error + * @return the corresponding I/O exception + */ + static IOException toIOException(UsbException e) { + if (e instanceof UsbTimeoutException) { + var ioException = new InterruptedIOException(e.getMessage()); + ioException.initCause(e); + return ioException; + } + return new IOException(e.getMessage(), e); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/ScopeCleanup.java b/java-does-usb/src/main/java/net/codecrete/usb/common/ScopeCleanup.java index 4624a2d2..44f0d8ce 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/ScopeCleanup.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/ScopeCleanup.java @@ -8,6 +8,7 @@ package net.codecrete.usb.common; import java.util.ArrayList; +import java.util.List; /** * Auto closeable object for clean up actions. @@ -31,7 +32,7 @@ */ public class ScopeCleanup implements AutoCloseable { - private final ArrayList cleanupActions = new ArrayList<>(); + private final List cleanupActions = new ArrayList<>(); /** * Registers a cleanup action to be run later. diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/USBAlternateInterfaceImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/USBAlternateInterfaceImpl.java deleted file mode 100644 index 401ba45e..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/USBAlternateInterfaceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.common; - -import net.codecrete.usb.USBAlternateInterface; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBEndpoint; - -import java.util.List; - -import static java.util.Collections.unmodifiableList; - -public class USBAlternateInterfaceImpl implements USBAlternateInterface { - - private final int alternateInterfaceNumber; - private final int alternateInterfaceClass; - private final int alternateInterfaceSubclass; - private final int alternateInterfaceProtocol; - private final List endpointList; - - public USBAlternateInterfaceImpl(int number, int classCode, int subclassCode, int protocolCode, - List endpoints) { - alternateInterfaceNumber = number; - alternateInterfaceClass = classCode; - alternateInterfaceSubclass = subclassCode; - alternateInterfaceProtocol = protocolCode; - endpointList = endpoints; - } - - @Override - public int number() { - return alternateInterfaceNumber; - } - - @Override - public int classCode() { - return alternateInterfaceClass; - } - - @Override - public int subclassCode() { - return alternateInterfaceSubclass; - } - - @Override - public int protocolCode() { - return alternateInterfaceProtocol; - } - - @Override - public List endpoints() { - return unmodifiableList(endpointList); - } - - void addEndpoint(USBEndpoint endpoint) { - endpointList.add(endpoint); - } - - @Override - public USBEndpoint getEndpoint(int endpointNumber, USBDirection direction) { - return endpointList.stream().filter(ep -> ep.number() == endpointNumber && ep.direction() == direction).findFirst().orElse(null); - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/USBInterfaceImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/USBInterfaceImpl.java deleted file mode 100644 index 07234665..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/USBInterfaceImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.common; - -import net.codecrete.usb.USBAlternateInterface; -import net.codecrete.usb.USBInterface; - -import java.util.Collections; -import java.util.List; - -public class USBInterfaceImpl implements USBInterface { - - private final int interfaceNumber; - private USBAlternateInterface currentAlternate; - private final List alternateInterfaces; - - private boolean claimed; - - public USBInterfaceImpl(int number, List alternates) { - interfaceNumber = number; - alternateInterfaces = alternates; - currentAlternate = alternates.get(0); - } - - @Override - public int number() { - return interfaceNumber; - } - - @Override - public boolean isClaimed() { - return claimed; - } - - public void setClaimed(boolean claimed) { - this.claimed = claimed; - } - - @Override - public USBAlternateInterface alternate() { - return currentAlternate; - } - - @Override - public USBAlternateInterface getAlternate(int alternateNumber) { - return alternateInterfaces.stream().filter(alt -> alt.number() == alternateNumber).findFirst().orElse(null); - } - - @Override - public List alternates() { - return Collections.unmodifiableList(alternateInterfaces); - } - - void addAlternate(USBAlternateInterface alt) { - alternateInterfaces.add(alt); - } - - public void setAlternate(USBAlternateInterface alternate) { - currentAlternate = alternate; - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/UsbAlternateInterfaceImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbAlternateInterfaceImpl.java new file mode 100644 index 00000000..9a7d70b1 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbAlternateInterfaceImpl.java @@ -0,0 +1,74 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.common; + +import net.codecrete.usb.UsbAlternateInterface; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbEndpoint; +import net.codecrete.usb.UsbException; +import org.jetbrains.annotations.NotNull; + +import java.util.Comparator; +import java.util.List; + +import static java.util.Collections.unmodifiableList; + +public class UsbAlternateInterfaceImpl implements UsbAlternateInterface { + + private final int alternateInterfaceNumber; + private final int alternateInterfaceClass; + private final int alternateInterfaceSubclass; + private final int alternateInterfaceProtocol; + private final List endpointList; + + public UsbAlternateInterfaceImpl(int number, int classCode, int subclassCode, int protocolCode, + List endpoints) { + alternateInterfaceNumber = number; + alternateInterfaceClass = classCode; + alternateInterfaceSubclass = subclassCode; + alternateInterfaceProtocol = protocolCode; + endpointList = endpoints; + endpointList.sort(Comparator.comparingInt(UsbEndpoint::getNumber)); + } + + @Override + public int getNumber() { + return alternateInterfaceNumber; + } + + @Override + public int getClassCode() { + return alternateInterfaceClass; + } + + @Override + public int getSubclassCode() { + return alternateInterfaceSubclass; + } + + @Override + public int getProtocolCode() { + return alternateInterfaceProtocol; + } + + @Override + public @NotNull List getEndpoints() { + return unmodifiableList(endpointList); + } + + void addEndpoint(UsbEndpoint endpoint) { + endpointList.add(endpoint); + } + + @Override + public @NotNull UsbEndpoint getEndpoint(int endpointNumber, UsbDirection direction) { + return endpointList.stream() + .filter(ep -> ep.getNumber() == endpointNumber && ep.getDirection() == direction).findFirst() + .orElseThrow(() -> new UsbException(String.format("Endpoint %d (%s) does not exist", endpointNumber, direction))); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceImpl.java similarity index 58% rename from java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceImpl.java rename to java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceImpl.java index 6db36ed5..41a1fb4f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceImpl.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceImpl.java @@ -7,18 +7,35 @@ package net.codecrete.usb.common; -import net.codecrete.usb.*; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbEndpoint; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbInterface; +import net.codecrete.usb.UsbTimeoutException; +import net.codecrete.usb.UsbTransferType; +import net.codecrete.usb.Version; import net.codecrete.usb.usbstandard.DeviceDescriptor; +import org.jetbrains.annotations.NotNull; import java.lang.foreign.MemorySegment; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.function.IntFunction; +import static java.lang.System.Logger.Level.WARNING; import static java.lang.foreign.ValueLayout.JAVA_BYTE; @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") -public abstract class USBDeviceImpl implements USBDevice { +public abstract class UsbDeviceImpl implements UsbDevice { + + private static final System.Logger LOG = System.getLogger(UsbDeviceImpl.class.getName()); + + // Maximum time (ms) to wait for the completion of a transfer that was aborted due to a + // timeout. If the abort's completion is never delivered (e.g. after an unplug), the wait + // degrades to a logged warning instead of a permanent hang. The transfer is then abandoned. + private static final long ABORT_COMPLETION_TIMEOUT_MS = 1000; /** * Operating system-specific device ID used for {@link #equals(Object)} and {@link #hashCode()}. @@ -29,7 +46,7 @@ public abstract class USBDeviceImpl implements USBDevice { */ protected final Object uniqueDeviceId; - protected List interfaceList; + protected List interfaceList; protected byte[] rawDeviceDescriptor; @@ -44,8 +61,11 @@ public abstract class USBDeviceImpl implements USBDevice { protected int deviceClass; protected int deviceSubclass; protected int deviceProtocol; - protected Version versionUSB; + protected Version versionUsb; protected Version versionDevice; + // volatile: written by the device monitor thread in disconnect(), read unlocked + // via isConnected() and checkIsClosed() + protected volatile boolean connected; /** * Creates a new instance. @@ -54,93 +74,106 @@ public abstract class USBDeviceImpl implements USBDevice { * @param vendorId USB vendor ID * @param productId USB product ID */ - protected USBDeviceImpl(Object id, int vendorId, int productId) { + protected UsbDeviceImpl(Object id, int vendorId, int productId) { assert id != null; uniqueDeviceId = id; vid = vendorId; pid = productId; + connected = true; } @Override public void detachStandardDrivers() { - if (isOpen()) - throw new USBException("detachStandardDrivers() must not be called while the device is open"); + if (isOpened()) + throw new UsbException("detachStandardDrivers() must not be called while the device is open"); // default implementation: do nothing } @Override public void attachStandardDrivers() { - if (isOpen()) - throw new USBException("attachStandardDrivers() must not be called while the device is open"); + if (isOpened()) + throw new UsbException("attachStandardDrivers() must not be called while the device is open"); // default implementation: do nothing } protected void checkIsOpen() { - if (!isOpen()) - throw new USBException("device needs to be opened first for this operation"); + if (!isOpened()) + throw new UsbException("device needs to be opened first for this operation"); + } + + protected void checkIsClosed(String message) { + if (!connected) + throw new UsbException("device has been disconnected"); + if (isOpened()) + throw new UsbException(message); + } + + protected synchronized void disconnect() { + connected = false; + close(); } @Override - public int productId() { + public int getProductId() { return pid; } @Override - public int vendorId() { + public int getVendorId() { return vid; } @Override - public String product() { + public String getProduct() { return productString; } @Override - public String manufacturer() { + public String getManufacturer() { return manufacturerString; } @Override - public String serialNumber() { + public String getSerialNumber() { return serialString; } @Override - public int classCode() { + public int getClassCode() { return deviceClass; } @Override - public int subclassCode() { + public int getSubclassCode() { return deviceSubclass; } @Override - public int protocolCode() { + public int getProtocolCode() { return deviceProtocol; } @Override - public Version usbVersion() { - return versionUSB; + public @NotNull Version getUsbVersion() { + return versionUsb; } @Override - public Version deviceVersion() { + public @NotNull Version getDeviceVersion() { return versionDevice; } @Override - public byte[] configurationDescriptor() { + public byte @NotNull [] getConfigurationDescriptor() { return rawConfigurationDescriptor; } @Override - public byte[] deviceDescriptor() { + public byte @NotNull [] getDeviceDescriptor() { return rawDeviceDescriptor; } @@ -148,6 +181,11 @@ public Object getUniqueId() { return uniqueDeviceId; } + @Override + public boolean isConnected() { + return connected; + } + /** * Sets the class codes and version for the device descriptor. * @@ -159,7 +197,7 @@ public void setFromDeviceDescriptor(MemorySegment descriptor) { deviceClass = deviceDescriptor.deviceClass() & 255; deviceSubclass = deviceDescriptor.deviceSubClass() & 255; deviceProtocol = deviceDescriptor.deviceProtocol() & 255; - versionUSB = new Version(deviceDescriptor.usbVersion()); + versionUsb = new Version(deviceDescriptor.usbVersion()); versionDevice = new Version(deviceDescriptor.deviceVersion()); } @@ -173,6 +211,7 @@ protected Configuration setConfigurationDescriptor(MemorySegment descriptor) { rawConfigurationDescriptor = descriptor.toArray(JAVA_BYTE); var configuration = ConfigurationParser.parseConfigurationDescriptor(descriptor); interfaceList = configuration.interfaces(); + interfaceList.sort(Comparator.comparingInt(UsbInterface::getNumber)); return configuration; } @@ -192,7 +231,7 @@ public void setProductStrings(String manufacturer, String product, String serial /** * Sets the product strings from the device descriptor. *

- * To lookup the string, a lookup function is provided. It takes the + * To look up the string, a lookup function is provided. It takes the * string ID and returns the string from the string descriptor. *

* @@ -213,51 +252,51 @@ public void setClassCodes(int classCode, int subclassCode, int protocolCode) { } public void setVersions(int usbVersion, int deviceVersion) { - versionUSB = new Version(usbVersion); + versionUsb = new Version(usbVersion); versionDevice = new Version(deviceVersion); } @Override - public List interfaces() { + public @NotNull List getInterfaces() { return Collections.unmodifiableList(interfaceList); } public void setClaimed(int interfaceNumber, boolean claimed) { for (var intf : interfaceList) { - if (intf.number() == interfaceNumber) { - ((USBInterfaceImpl) intf).setClaimed(claimed); + if (intf.getNumber() == interfaceNumber) { + ((UsbInterfaceImpl) intf).setClaimed(claimed); return; } } - throw new USBException("internal error (interface not found)"); + throw new UsbException("internal error (interface not found)"); } @Override - public USBInterfaceImpl getInterface(int interfaceNumber) { - return (USBInterfaceImpl) interfaceList.stream().filter(intf -> intf.number() == interfaceNumber).findFirst().orElse(null); + public @NotNull UsbInterfaceImpl getInterface(int interfaceNumber) { + return (UsbInterfaceImpl) interfaceList.stream() + .filter(intf -> intf.getNumber() == interfaceNumber).findFirst() + .orElseThrow(() -> new UsbException(String.format("USB device has no interface %d", interfaceNumber))); } - public USBInterfaceImpl getInterfaceWithCheck(int interfaceNumber, boolean isClaimed) { + public UsbInterfaceImpl getInterfaceWithCheck(int interfaceNumber, boolean isClaimed) { var intf = getInterface(interfaceNumber); - if (intf == null) - throw new USBException(String.format("invalid interface number: %d", interfaceNumber)); if (isClaimed && !intf.isClaimed()) { - throw new USBException(String.format("interface %d must be claimed first", interfaceNumber)); + throw new UsbException(String.format("interface %d must be claimed first", interfaceNumber)); } else if (!isClaimed && intf.isClaimed()) { - throw new USBException(String.format("interface %d has already been claimed", interfaceNumber)); + throw new UsbException(String.format("interface %d has already been claimed", interfaceNumber)); } return intf; } @Override - public USBEndpoint getEndpoint(USBDirection direction, int endpointNumber) { + public @NotNull UsbEndpoint getEndpoint(UsbDirection direction, int endpointNumber) { for (var intf : interfaceList) { - for (var endpoint : intf.alternate().endpoints()) { - if (endpoint.direction() == direction && endpoint.number() == endpointNumber) + for (var endpoint : intf.getCurrentAlternate().getEndpoints()) { + if (endpoint.getDirection() == direction && endpoint.getNumber() == endpointNumber) return endpoint; } } - return null; + throw new UsbException(String.format("endpoint %d (%s) does not exist", endpointNumber, direction.name())); } /** @@ -270,20 +309,20 @@ public USBEndpoint getEndpoint(USBDirection direction, int endpointNumber) { * @return endpoint */ @SuppressWarnings("java:S3776") - protected EndpointInfo getEndpoint(USBDirection direction, int endpointNumber, USBTransferType transferType1, - USBTransferType transferType2) { + protected EndpointInfo getEndpoint(UsbDirection direction, int endpointNumber, UsbTransferType transferType1, + UsbTransferType transferType2) { checkIsOpen(); if (endpointNumber >= 1 && endpointNumber <= 127) { for (var intf : interfaceList) { if (intf.isClaimed()) { - for (var ep : intf.alternate().endpoints()) { - if (ep.number() == endpointNumber && ep.direction() == direction - && (ep.transferType() == transferType1 || ep.transferType() == transferType2)) - return new EndpointInfo(intf.number(), ep.number(), - (byte) (endpointNumber | (direction == USBDirection.IN ? 0x80 : 0)), - ep.packetSize(), ep.transferType()); + for (var ep : intf.getCurrentAlternate().getEndpoints()) { + if (ep.getNumber() == endpointNumber && ep.getDirection() == direction + && (ep.getTransferType() == transferType1 || ep.getTransferType() == transferType2)) + return new EndpointInfo(intf.getNumber(), ep.getNumber(), + (byte) (endpointNumber | (direction == UsbDirection.IN ? 0x80 : 0)), + ep.getPacketSize(), ep.getTransferType()); } } } @@ -293,27 +332,27 @@ protected EndpointInfo getEndpoint(USBDirection direction, int endpointNumber, U return null; // will never be reached } - protected void throwInvalidEndpointException(USBDirection direction, int endpointNumber, - USBTransferType transferType1, USBTransferType transferType2) { + protected void throwInvalidEndpointException(UsbDirection direction, int endpointNumber, + UsbTransferType transferType1, UsbTransferType transferType2) { String transferTypeDesc; if (transferType2 == null) transferTypeDesc = transferType1.name(); else transferTypeDesc = String.format("%s or %s", transferType1.name(), transferType2.name()); - throw new USBException(String.format( + throw new UsbException(String.format( "endpoint number %d does not exist, is not part of a claimed interface or is not valid for %s transfer in %s direction", endpointNumber, transferTypeDesc, direction.name())); } - protected int getInterfaceNumber(USBDirection direction, int endpointNumber) { + protected int getInterfaceNumber(UsbDirection direction, int endpointNumber) { if (endpointNumber < 1 || endpointNumber > 127) return -1; for (var intf : interfaceList) { if (intf.isClaimed()) { - for (var ep : intf.alternate().endpoints()) { - if (ep.number() == endpointNumber && ep.direction() == direction) - return intf.number(); + for (var ep : intf.getCurrentAlternate().getEndpoints()) { + if (ep.getNumber() == endpointNumber && ep.getDirection() == direction) + return intf.getNumber(); } } } @@ -322,21 +361,21 @@ protected int getInterfaceNumber(USBDirection direction, int endpointNumber) { } @Override - public void transferOut(int endpointNumber, byte[] data) { + public void transferOut(int endpointNumber, byte @NotNull [] data) { transferOut(endpointNumber, data, 0, data.length, 0); } @Override - public void transferOut(int endpointNumber, byte[] data, int timeout) { + public void transferOut(int endpointNumber, byte @NotNull [] data, int timeout) { transferOut(endpointNumber, data, 0, data.length, timeout); } @Override - public byte[] transferIn(int endpointNumber) { + public byte @NotNull [] transferIn(int endpointNumber) { return transferIn(endpointNumber, 0); } - protected void waitForTransfer(Transfer transfer, int timeout, USBDirection direction, int endpointNumber) { + protected void waitForTransfer(Transfer transfer, int timeout, UsbDirection direction, int endpointNumber) { if (timeout <= 0) { waitNoTimeout(transfer); @@ -346,9 +385,17 @@ protected void waitForTransfer(Transfer transfer, int timeout, USBDirection dire // test for timeout if (hasTimedOut && transfer.resultCode() == 0) { abortTransfers(direction, endpointNumber); - waitNoTimeout(transfer); - throw new USBTimeoutException(getOperationDescription(direction, endpointNumber) - + "aborted due to timeout"); + + // Wait for the abort's completion, but bounded: if it never arrives (device + // vanished such that neither the transfer nor the abort yields a callback), + // abandon the transfer instead of blocking forever. Abandoning is safe because + // buffers reaching this path come from an auto arena and survive a late completion. + var abortCompleted = !waitWithTimeout(transfer, (int) ABORT_COMPLETION_TIMEOUT_MS); + if (!abortCompleted) + LOG.log(WARNING, "abort completion for {0} did not arrive within {1} ms - abandoning transfer", + getOperationDescription(direction, endpointNumber), ABORT_COMPLETION_TIMEOUT_MS); + + throw new UsbTimeoutException(getOperationDescription(direction, endpointNumber) + " aborted due to timeout"); } } @@ -359,37 +406,50 @@ protected void waitForTransfer(Transfer transfer, int timeout, USBDirection dire } } - @SuppressWarnings("java:S2273") + @SuppressWarnings({"java:S2273", "java:S2142"}) private static void waitNoTimeout(Transfer transfer) { - // wait for transfer + // wait for transfer. + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // inside the loop (which would make the next wait() throw immediately and + // busy-spin). Re-assert once the transfer has actually completed. + var wasInterrupted = false; while (transfer.resultSize() == -1) { try { transfer.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException _) { + wasInterrupted = true; } } + if (wasInterrupted) + Thread.currentThread().interrupt(); } - @SuppressWarnings("java:S2273") + @SuppressWarnings({"java:S2273", "java:S2142"}) private static boolean waitWithTimeout(Transfer transfer, int timeout) { - // wait for transfer to complete, or abort when timeout occurs + // wait for transfer to complete, or abort when timeout occurs. + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // inside the loop (which would make the next wait() throw immediately and + // busy-spin). The remaining timeout is recomputed on both the normal and the + // interrupted path, so the wait stays bounded by the original expiration. var expiration = System.currentTimeMillis() + timeout; long remainingTimeout = timeout; + var wasInterrupted = false; while (remainingTimeout > 0 && transfer.resultSize() == -1) { try { transfer.wait(remainingTimeout); - remainingTimeout = expiration - System.currentTimeMillis(); - - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException _) { + wasInterrupted = true; } + remainingTimeout = expiration - System.currentTimeMillis(); } + if (wasInterrupted) + Thread.currentThread().interrupt(); + return remainingTimeout <= 0; } - protected static String getOperationDescription(USBDirection direction, int endpointNumber) { + protected static String getOperationDescription(UsbDirection direction, int endpointNumber) { if (endpointNumber == 0) { return "control transfer"; } else { @@ -436,7 +496,7 @@ public boolean equals(Object o) { return true; if (o == null || getClass() != o.getClass()) return false; - var that = (USBDeviceImpl) o; + var that = (UsbDeviceImpl) o; return uniqueDeviceId.equals(that.uniqueDeviceId); } @@ -447,10 +507,11 @@ public int hashCode() { @Override public String toString() { - return "VID: 0x" + String.format("%04x", vid) + ", PID: 0x" + String.format("%04x", pid) + ", " + "manufacturer: " + manufacturerString + ", product: " + productString + ", serial: " + serialString + ", ID: " + uniqueDeviceId; + return String.format("VID: 0x%04x, PID: 0x%04x, manufacturer: %s, product: %s, serial: %s, ID: %s", + vid, pid, manufacturerString, productString, serialString, uniqueDeviceId); } public record EndpointInfo(int interfaceNumber, int endpointNumber, byte endpointAddress, int packetSize, - USBTransferType transferType) { + UsbTransferType transferType) { } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceRegistry.java b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceRegistry.java similarity index 77% rename from java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceRegistry.java rename to java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceRegistry.java index b3224dfc..ed7999af 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceRegistry.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbDeviceRegistry.java @@ -7,11 +7,10 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBDevice; -import net.codecrete.usb.USBException; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -33,14 +32,16 @@ * and builds the initial device list. *

*/ -public abstract class USBDeviceRegistry { +@SuppressWarnings("java:S3077") +public abstract class UsbDeviceRegistry { - private static final System.Logger LOG = System.getLogger(USBDeviceRegistry.class.getName()); + private static final System.Logger LOG = System.getLogger(UsbDeviceRegistry.class.getName()); - private List devices; + private List devices; private Throwable failureCause; - protected Consumer onDeviceConnectedHandler; - protected Consumer onDeviceDisconnectedHandler; + // volatile: set by the application thread, read by the device monitor thread + protected volatile Consumer onDeviceConnectedHandler; + protected volatile Consumer onDeviceDisconnectedHandler; private final Lock lock = new ReentrantLock(); private final Condition enumerationComplete = lock.newCondition(); @@ -74,36 +75,39 @@ public void start() { * * @return list of devices */ - public synchronized List getAllDevices() { - return Collections.unmodifiableList(devices); + public synchronized List getAllDevices() { + return devices; } - public void setOnDeviceConnected(Consumer handler) { + public void setOnDeviceConnected(Consumer handler) { onDeviceConnectedHandler = handler; } - public void setOnDeviceDisconnected(Consumer handler) { + public void setOnDeviceDisconnected(Consumer handler) { onDeviceDisconnectedHandler = handler; } - protected void emitOnDeviceConnected(USBDevice device) { - if (onDeviceConnectedHandler == null) + protected void emitOnDeviceConnected(UsbDevice device) { + // read once so a concurrent setOnDeviceConnected(null) cannot fail between check and call + var handler = onDeviceConnectedHandler; + if (handler == null) return; try { - onDeviceConnectedHandler.accept(device); + handler.accept(device); } catch (Exception e) { LOG.log(WARNING, "unhandled exception in 'onDeviceConnected' handler - ignoring", e); } } - protected void emitOnDeviceDisconnected(USBDevice device) { - if (onDeviceDisconnectedHandler == null) + protected void emitOnDeviceDisconnected(UsbDevice device) { + var handler = onDeviceDisconnectedHandler; + if (handler == null) return; try { - onDeviceDisconnectedHandler.accept(device); + handler.accept(device); } catch (Exception e) { LOG.log(WARNING, "unhandled exception in 'onDeviceDisconnected' handler - ignoring", e); @@ -136,7 +140,7 @@ protected void startDeviceMonitor(Runnable monitorTask) { } if (failureCause != null) - throw new USBException("initial device enumeration has failed", failureCause); + throw new UsbException("initial device enumeration has failed", failureCause); } /** @@ -169,7 +173,7 @@ protected void enumerationFailed(Throwable e) { * * @param deviceList the device list */ - protected void setInitialDeviceList(List deviceList) { + protected void setInitialDeviceList(List deviceList) { synchronized (this) { devices = deviceList; } @@ -181,14 +185,14 @@ protected void setInitialDeviceList(List deviceList) { * * @param device device to add */ - protected void addDevice(USBDevice device) { + protected void addDevice(UsbDevice device) { synchronized (this) { // check for duplicates - if (findDeviceIndex(devices, ((USBDeviceImpl) device).getUniqueId()) >= 0) + if (findDeviceIndex(devices, ((UsbDeviceImpl) device).getUniqueId()) >= 0) return; // copy list - var newDeviceList = new ArrayList(devices.size() + 1); + var newDeviceList = new ArrayList(devices.size() + 1); newDeviceList.addAll(devices); newDeviceList.add(device); devices = newDeviceList; @@ -205,9 +209,9 @@ protected void closeAndRemoveDevice(Object deviceId) { return; try { - device.close(); + ((UsbDeviceImpl) device).disconnect(); } catch (Exception e) { - LOG.log(INFO, "failed to close USB device - ignoring exception", e); + LOG.log(INFO, "failed to close disconnected USB device - ignoring exception", e); } removeDevice(deviceId); @@ -219,7 +223,7 @@ protected void closeAndRemoveDevice(Object deviceId) { * @param deviceId the unique ID of the device to remove */ protected void removeDevice(Object deviceId) { - USBDevice device; + UsbDevice device; synchronized (this) { // locate device to be removed int index = findDeviceIndex(devices, deviceId); @@ -244,9 +248,9 @@ protected void removeDevice(Object deviceId) { * @param deviceId the unique device ID * @return return the index, or -1 if the device is not found */ - protected int findDeviceIndex(List deviceList, Object deviceId) { + protected int findDeviceIndex(List deviceList, Object deviceId) { for (int i = 0; i < deviceList.size(); i++) { - var dev = (USBDeviceImpl) deviceList.get(i); + var dev = (UsbDeviceImpl) deviceList.get(i); if (deviceId.equals(dev.getUniqueId())) return i; } @@ -259,7 +263,7 @@ protected int findDeviceIndex(List deviceList, Object deviceId) { * @param deviceId the unique device ID * @return return device, or {@code null} if not found. */ - protected USBDevice findDevice(Object deviceId) { + protected UsbDevice findDevice(Object deviceId) { int index = findDeviceIndex(devices, deviceId); if (index < 0) return null; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/USBEndpointImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbEndpointImpl.java similarity index 51% rename from java-does-usb/src/main/java/net/codecrete/usb/common/USBEndpointImpl.java rename to java-does-usb/src/main/java/net/codecrete/usb/common/UsbEndpointImpl.java index f896b0f2..f40525ea 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/common/USBEndpointImpl.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbEndpointImpl.java @@ -7,21 +7,21 @@ package net.codecrete.usb.common; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBEndpoint; -import net.codecrete.usb.USBTransferType; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbEndpoint; +import net.codecrete.usb.UsbTransferType; /** - * Implementation of {@code USBEndpoint} interface. + * Implementation of {@code UsbEndpoint} interface. */ -public class USBEndpointImpl implements USBEndpoint { +public class UsbEndpointImpl implements UsbEndpoint { private final int endpointNumber; - private final USBDirection transferDirection; - private final USBTransferType type; + private final UsbDirection transferDirection; + private final UsbTransferType type; private final int maxPacketSize; - public USBEndpointImpl(int number, USBDirection direction, USBTransferType type, int packetSize) { + public UsbEndpointImpl(int number, UsbDirection direction, UsbTransferType type, int packetSize) { endpointNumber = number; transferDirection = direction; this.type = type; @@ -29,22 +29,22 @@ public USBEndpointImpl(int number, USBDirection direction, USBTransferType type, } @Override - public int number() { + public int getNumber() { return endpointNumber; } @Override - public USBDirection direction() { + public UsbDirection getDirection() { return transferDirection; } @Override - public USBTransferType transferType() { + public UsbTransferType getTransferType() { return type; } @Override - public int packetSize() { + public int getPacketSize() { return maxPacketSize; } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/common/UsbInterfaceImpl.java b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbInterfaceImpl.java new file mode 100644 index 00000000..64697e87 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/common/UsbInterfaceImpl.java @@ -0,0 +1,75 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.common; + +import net.codecrete.usb.UsbAlternateInterface; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbInterface; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class UsbInterfaceImpl implements UsbInterface { + + private final int interfaceNumber; + private UsbAlternateInterface currentAlternate; + private final List alternateInterfaces; + + private boolean claimed; + + public UsbInterfaceImpl(int number, List alternates) { + interfaceNumber = number; + alternateInterfaces = alternates; + currentAlternate = alternates.getFirst(); + alternateInterfaces.sort(Comparator.comparingInt(UsbAlternateInterface::getNumber)); + } + + @Override + public int getNumber() { + return interfaceNumber; + } + + @Override + public boolean isClaimed() { + return claimed; + } + + public void setClaimed(boolean claimed) { + this.claimed = claimed; + } + + @Override + public @NotNull UsbAlternateInterface getCurrentAlternate() { + return currentAlternate; + } + + @Override + public @NotNull UsbAlternateInterface getAlternate(int alternateNumber) { + return alternateInterfaces.stream() + .filter(alt -> alt.getNumber() == alternateNumber).findFirst() + .orElseThrow(() -> new UsbException(String.format( + "Interface %d does not have an alternate interface setting %d", + interfaceNumber, alternateNumber) + )); + } + + @Override + public @NotNull List getAlternates() { + return Collections.unmodifiableList(alternateInterfaces); + } + + void addAlternate(UsbAlternateInterface alt) { + alternateInterfaces.add(alt); + } + + public void setAlternate(UsbAlternateInterface alternate) { + currentAlternate = alternate; + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java new file mode 100644 index 00000000..38b9d5bb --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/EPoll.java @@ -0,0 +1,140 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.linux; + +import net.codecrete.usb.linux.gen.errno.errno; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.Linker; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.ADDRESS_UNALIGNED; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED; +import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED; +import static net.codecrete.usb.linux.Linux.allocateErrorState; +import static net.codecrete.usb.linux.LinuxUsbException.throwLastError; +import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_ADD; +import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLL_CTL_DEL; + +@SuppressWarnings({"OptionalGetWithoutIsPresent", "SameParameterValue", "java:S100", "java:S1192"}) +public class EPoll { + private EPoll() { } + + private static final boolean IS_AARCH64 = System.getProperty("os.arch").equals("aarch64"); + + private static final GroupLayout DATA$LAYOUT = MemoryLayout.unionLayout( + ADDRESS_UNALIGNED.withName("ptr"), + JAVA_INT_UNALIGNED.withName("fd"), + JAVA_INT_UNALIGNED.withName("u32"), + JAVA_LONG_UNALIGNED.withName("u64") + ).withName("epoll_data"); + + static final GroupLayout EVENT$LAYOUT = IS_AARCH64 ? + MemoryLayout.structLayout( + JAVA_INT.withName("events"), + MemoryLayout.paddingLayout(4), + DATA$LAYOUT.withName("data") + ).withName("epoll_event") : + MemoryLayout.structLayout( + JAVA_INT_UNALIGNED.withName("events"), + DATA$LAYOUT.withName("data") + ).withName("epoll_event"); + + // varhandle to access the "fd" field in an epoll_event array + static final VarHandle EVENT_ARRAY_DATA_FD$VH = EVENT$LAYOUT.arrayElementVarHandle( + MemoryLayout.PathElement.groupElement("data"), + MemoryLayout.PathElement.groupElement("fd") + ); + + // varhandle to access the "fd" field in an epoll_event struct + private static final VarHandle EVENT_DATA_FD$VH = EVENT$LAYOUT.varHandle( + MemoryLayout.PathElement.groupElement("data"), + MemoryLayout.PathElement.groupElement("fd") + ); + + private static final VarHandle EVENTS$VH = EVENT$LAYOUT.varHandle( + MemoryLayout.PathElement.groupElement("events") + ); + + private static final Linker linker = Linker.nativeLinker(); + + private static final FunctionDescriptor epoll_create1$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT); + private static final MethodHandle epoll_create1$MH = linker.downcallHandle(linker.defaultLookup().find( + "epoll_create").get(), epoll_create1$FUNC, Linux.ERRNO_STATE); + + private static final FunctionDescriptor epoll_ctl$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + private static final MethodHandle epoll_ctl$MH = linker.downcallHandle(linker.defaultLookup().find( + "epoll_ctl").get(), epoll_ctl$FUNC, Linux.ERRNO_STATE); + + private static final FunctionDescriptor epoll_wait$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT); + private static final MethodHandle epoll_wait$MH = linker.downcallHandle(linker.defaultLookup().find( + "epoll_wait").get(), epoll_wait$FUNC, Linux.ERRNO_STATE); + + static int epoll_create1(int flags, MemorySegment errno) { + try { + return (int) epoll_create1$MH.invokeExact(errno, flags); + } catch (Throwable ex) { + throw new AssertionError(ex); + } + } + + private static int epoll_ctl(int epfd, int op, int fd, MemorySegment event, MemorySegment errno) { + try { + return (int) epoll_ctl$MH.invokeExact(errno, epfd, op, fd, event); + } catch (Throwable ex) { + throw new AssertionError(ex); + } + } + + static int epoll_wait(int epfd, MemorySegment events, int maxevent, int timeout, MemorySegment errno) { + try { + return (int) epoll_wait$MH.invokeExact(errno, epfd, events, maxevent, timeout); + } catch (Throwable ex) { + throw new AssertionError(ex); + } + } + + static void addFileDescriptor(int epfd, int op, int fd) { + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + + var event = arena.allocate(EVENT$LAYOUT); + EVENTS$VH.set(event, 0, op); + EVENT_DATA_FD$VH.set(event, 0, fd); + var ret = epoll_ctl(epfd, EPOLL_CTL_ADD(), fd, event, errorState); + if (ret < 0) + throwLastError(errorState, "internal error (epoll_ctl_add)"); + } + } + + static void removeFileDescriptor(int epfd, int fd) { + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + + var event = arena.allocate(EVENT$LAYOUT); + EVENTS$VH.set(event, 0, 0); + EVENT_DATA_FD$VH.set(event, 0, fd); + var ret = epoll_ctl(epfd, EPOLL_CTL_DEL(), fd, event, errorState); + if (ret < 0) { + var err = Linux.getErrno(errorState); + // ignore ENOENT as this method might be called twice when cleaning up, + // and EBADF as the file descriptor might have been closed concurrently + // (closing deregisters it from epoll anyway) + if (err != errno.ENOENT() && err != errno.EBADF()) + throwLastError(errorState, "internal error (epoll_ctl_del)"); + } + } + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java index 88b6d364..367deb80 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java @@ -12,7 +12,9 @@ import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; @SuppressWarnings({"OptionalGetWithoutIsPresent", "SameParameterValue", "java:S100"}) class IO { @@ -27,15 +29,6 @@ private IO() { private static final FunctionDescriptor open$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT); private static final MethodHandle open$MH = linker.downcallHandle(linker.defaultLookup().find("open").get(), open$FUNC, Linux.ERRNO_STATE); - private static final FunctionDescriptor eventfd$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); - private static final MethodHandle eventfd$MH = linker.downcallHandle(linker.defaultLookup().find("eventfd").get() - , eventfd$FUNC, Linux.ERRNO_STATE); - private static final FunctionDescriptor eventfd_read$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); - private static final MethodHandle eventfd_read$MH = linker.downcallHandle(linker.defaultLookup().find( - "eventfd_read").get(), eventfd_read$FUNC, Linux.ERRNO_STATE); - private static final FunctionDescriptor eventfd_write$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_LONG); - private static final MethodHandle eventfd_write$MH = linker.downcallHandle(linker.defaultLookup().find( - "eventfd_write").get(), eventfd_write$FUNC, Linux.ERRNO_STATE); static int ioctl(int fd, long request, MemorySegment segment, MemorySegment errno) { try { @@ -52,29 +45,4 @@ static int open(MemorySegment file, int oflag, MemorySegment errno) { throw new AssertionError(ex); } } - - static int eventfd(int count, int flags, MemorySegment errno) { - try { - return (int) eventfd$MH.invokeExact(errno, count, flags); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static int eventfd_read(int fd, MemorySegment value, MemorySegment errno) { - try { - return (int) eventfd_read$MH.invokeExact(errno, fd, value); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static int eventfd_write(int fd, long value, MemorySegment errno) { - try { - return (int) eventfd_write$MH.invokeExact(errno, fd, value); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/Linux.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/Linux.java index c8c7ac70..ab494b91 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/Linux.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/Linux.java @@ -43,7 +43,7 @@ static MemorySegment allocateErrorState(Arena arena) { * @return error message */ static String getErrorMessage(int err) { - return string.strerror(err).getUtf8String(0); + return string.strerror(err).getString(0); } /** @@ -56,6 +56,6 @@ static String getErrorMessage(int err) { * @return error code */ static int getErrno(MemorySegment errorState) { - return (int) callState_errno$VH.get(errorState); + return (int) callState_errno$VH.get(errorState, 0); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxAsyncTask.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxAsyncTask.java index 19d01492..3d6bf71f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxAsyncTask.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxAsyncTask.java @@ -7,10 +7,9 @@ package net.codecrete.usb.linux; -import net.codecrete.usb.USBTransferType; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbTransferType; import net.codecrete.usb.linux.gen.errno.errno; -import net.codecrete.usb.linux.gen.poll.poll; -import net.codecrete.usb.linux.gen.poll.pollfd; import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevfs_urb; import java.lang.foreign.Arena; @@ -20,14 +19,26 @@ import java.util.List; import java.util.Map; +import static java.lang.System.Logger.Level.ERROR; import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_LONG; import static net.codecrete.usb.common.ForeignMemory.dereference; +import static net.codecrete.usb.linux.EPoll.epoll_create1; +import static net.codecrete.usb.linux.EPoll.epoll_wait; import static net.codecrete.usb.linux.Linux.allocateErrorState; -import static net.codecrete.usb.linux.LinuxUSBException.throwException; -import static net.codecrete.usb.linux.LinuxUSBException.throwLastError; -import static net.codecrete.usb.linux.USBDevFS.*; -import static net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs.*; +import static net.codecrete.usb.linux.LinuxUsbException.throwException; +import static net.codecrete.usb.linux.LinuxUsbException.throwLastError; +import static net.codecrete.usb.linux.UsbDevFS.DISCARDURB; +import static net.codecrete.usb.linux.UsbDevFS.REAPURBNDELAY; +import static net.codecrete.usb.linux.UsbDevFS.SUBMITURB; +import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLLOUT; +import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLLWAKEUP; +import static net.codecrete.usb.linux.gen.errno.errno.EINTR; +import static net.codecrete.usb.linux.gen.errno.errno.ENODEV; +import static net.codecrete.usb.linux.gen.fcntl.fcntl.FD_CLOEXEC; +import static net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs.USBDEVFS_URB_TYPE_BULK; +import static net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs.USBDEVFS_URB_TYPE_CONTROL; +import static net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs.USBDEVFS_URB_TYPE_INTERRUPT; +import static net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs.USBDEVFS_URB_TYPE_ISO; /** * Background task for handling asynchronous transfers. @@ -46,20 +57,25 @@ */ @SuppressWarnings("java:S6548") class LinuxAsyncTask { + + private static final System.Logger LOG = System.getLogger(LinuxAsyncTask.class.getName()); + /** * Singleton instance of background task. */ static final LinuxAsyncTask INSTANCE = new LinuxAsyncTask(); + private static final int NUM_EVENTS = 5; + private final Arena urbArena = Arena.ofAuto(); /// available URBs private final List availableURBs = new ArrayList<>(); /// map of URB addresses to transfer (for outstanding transfers) private final Map transfersByURB = new LinkedHashMap<>(); - /// array of file descriptors using asynchronous completion - private int[] asyncFds; - /// file descriptor to notify async IO background thread about an update - private int asyncIOWakeUpEventFd; + /// file descriptor of epoll + private int epollFd = -1; + /// indicates that the background task has terminated due to an unrecoverable error + private boolean taskTerminated; /** * Background task for handling asynchronous IO completions. @@ -67,83 +83,64 @@ class LinuxAsyncTask { * It polls on all registered file descriptors. If a file descriptor is * ready, the URB is "reaped". *

- *

- * Using an additional {@code eventfd} file descriptor, this background task - * can be woken up to refresh the list of polled file descriptors. - *

*/ @SuppressWarnings({"java:S2189", "java:S135", "java:S3776"}) private void asyncCompletionTask() { try (var arena = Arena.ofConfined()) { var errorState = allocateErrorState(arena); - var pollfdArray = pollfd.allocateArray(100, arena); var urbPointerHolder = arena.allocate(ADDRESS); - var eventfdValueHolder = arena.allocate(JAVA_LONG); + var events = arena.allocate(EPoll.EVENT$LAYOUT, NUM_EVENTS); while (true) { - - // get current file descriptor array - int[] fds; - synchronized (this) { - fds = asyncFds; - } - - // poll for event - fillPollfdArray(pollfdArray, fds); - var n = fds.length; - var res = poll.poll(pollfdArray, n + 1L, -1); - if (res < 0) - throwException("internal error (poll)"); - - // acquire lock - synchronized (this) { - - // check for wakeup event - if ((pollfd.revents$get(pollfdArray, n) & poll.POLLIN()) != 0) { - // wakeup to refresh list of file descriptors - res = IO.eventfd_read(asyncIOWakeUpEventFd, eventfdValueHolder, errorState); - if (res < 0) - throwLastError(errorState, "internal error (eventfd_read)"); - continue; + try { + // wait for file descriptor to be ready + var res = epoll_wait(epollFd, events, NUM_EVENTS, -1, errorState); + if (res < 0) { + var err = Linux.getErrno(errorState); + if (err == EINTR()) + continue; // continue on interrupt + throwException(err, "internal error (epoll_wait)"); } - // check for USB device events - for (var i = 0; i < n + 1; i++) { - var revent = pollfd.revents$get(pollfdArray, i); - if (revent == 0) - continue; - - if ((revent & poll.POLLERR()) != 0) { - // most likely the device has been disconnected, - // remove from polled FD list to prevent further problems - var fd = pollfd.fd$get(pollfdArray, i); - removeFdFromAsyncIOCompletion(fd); - continue; - } - - // reap URB - var fd = pollfd.fd$get(pollfdArray, i); + // for all ready file descriptors, reap URBs + for (int i = 0; i < res; i++) { + var fd = (int) EPoll.EVENT_ARRAY_DATA_FD$VH.get(events, 0L, i); reapURBs(fd, urbPointerHolder, errorState); } + + } catch (Exception e) { + LOG.log(ERROR, "USB async IO thread failed and is terminating; " + + "all outstanding transfers will fail, and no further transfers are possible", e); + failAllPendingTransfers(); + return; } } } } - void fillPollfdArray(MemorySegment asyncPolls, int[] fds) { - // device file descriptors - var n = fds.length; - for (var i = 0; i < n; i++) { - pollfd.fd$set(asyncPolls, i, fds[i]); - pollfd.events$set(asyncPolls, i, (short) poll.POLLOUT()); - pollfd.revents$set(asyncPolls, i, (short) 0); + /** + * Fails all outstanding transfers and marks this task as terminated. + *

+ * Called when the background task can no longer dispatch completions. Waiters blocked + * on the failed transfers wake up with an error result instead of hanging forever, + * and future submissions are rejected. + *

+ */ + private void failAllPendingTransfers() { + var failedTransfers = new ArrayList(); + synchronized (this) { + taskTerminated = true; + for (var transfer : transfersByURB.values()) { + transfer.urb = null; + transfer.setResultCode(errno.ECANCELED()); + transfer.setResultSize(0); + failedTransfers.add(transfer); + } + transfersByURB.clear(); + availableURBs.clear(); } - - // entry n is the wake-up event file descriptor - pollfd.fd$set(asyncPolls, n, asyncIOWakeUpEventFd); - pollfd.events$set(asyncPolls, n, (short) poll.POLLIN()); - pollfd.revents$set(asyncPolls, n, (short) 0); + completeTransfers(failedTransfers); } /** @@ -154,38 +151,63 @@ void fillPollfdArray(MemorySegment asyncPolls, int[] fds) { * @param errorState native memory to receive the errno */ private void reapURBs(int fd, MemorySegment urbPointerHolder, MemorySegment errorState) { - while (true) { - var res = IO.ioctl(fd, REAPURBNDELAY, urbPointerHolder, errorState); - if (res < 0) { - var err = Linux.getErrno(errorState); - if (err == errno.EAGAIN()) - return; // no more pending URBs - if (err == errno.ENODEV()) - return; // ignore, device might have been closed - throwException(err, "internal error (reap URB)"); - } - // call completion handler - var urb = dereference(urbPointerHolder); - var transfer = getTransferResult(urb); - transfer.completion().completed(transfer); + var completedTransfers = new ArrayList(); + try { + synchronized (this) { + while (true) { + var res = IO.ioctl(fd, REAPURBNDELAY, urbPointerHolder, errorState); + if (res < 0) { + var err = Linux.getErrno(errorState); + if (err == errno.EAGAIN()) + return; // no more pending URBs + if (err == errno.EBADF()) + return; // file descriptor was closed concurrently (deregisters it from epoll) + if (err == errno.ENODEV()) { + // device might have been unplugged + EPoll.removeFileDescriptor(epollFd, fd); + return; + } + // Unexpected error: stop handling this device's completions but keep + // the task alive for all other devices. The file descriptor must be + // deregistered, or epoll would report it ready again immediately, + // resulting in a hot loop. + LOG.log(ERROR, "reaping URBs for file descriptor {0} failed with errno {1}; " + + "no further transfers will complete for this device", fd, err); + EPoll.removeFileDescriptor(epollFd, fd); + return; + } + + var urb = dereference(urbPointerHolder); + completedTransfers.add(getTransferWithResult(urb)); + } + } + } finally { + // Even if reaping fails, the already reaped transfers must be completed. + completeTransfers(completedTransfers); } } /** - * Notifies background process about changed FD list + * Calls the completion handlers of the specified transfers. + *

+ * Must be called without holding the lock: handlers acquire other monitors + * (transfer, device), and threads submitting transfers acquire this task's lock + * while holding those monitors, so calling handlers under the lock can deadlock. + *

+ * + * @param transfers completed transfers */ - private void notifyAsyncIOTask() { - // start background process if needed - if (asyncIOWakeUpEventFd == 0) { - startAsyncIOTask(); - return; - } - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - if (IO.eventfd_write(asyncIOWakeUpEventFd, 1, errorState) < 0) - throwLastError(errorState, "internal error (eventfd_write)"); + private void completeTransfers(List transfers) { + for (var transfer : transfers) { + try { + transfer.completion().completed(transfer); + } catch (Exception e) { + // This method also runs on the process-wide async IO thread. Any exception + // escaping would kill that thread and hang all async transfers for the + // entire library. + LOG.log(ERROR, "Unexpected exception while handling async IO completion", e); + } } } @@ -194,16 +216,12 @@ private void notifyAsyncIOTask() { * * @param device USB device */ - synchronized void addForAsyncIOCompletion(LinuxUSBDevice device) { - var n = asyncFds != null ? asyncFds.length : 0; - var fds = new int[n + 1]; - if (n > 0) - System.arraycopy(asyncFds, 0, fds, 0, n); - fds[n] = device.fileDescriptor(); - - // activate new array - asyncFds = fds; - notifyAsyncIOTask(); + synchronized void addForAsyncIOCompletion(LinuxUsbDevice device) { + // start background process if needed + if (epollFd < 0) + startAsyncIOTask(); + + EPoll.addFileDescriptor(epollFd, EPOLLOUT() | EPOLLWAKEUP(), device.fileDescriptor()); } /** @@ -211,46 +229,59 @@ synchronized void addForAsyncIOCompletion(LinuxUSBDevice device) { * * @param device USB device */ - synchronized void removeFromAsyncIOCompletion(LinuxUSBDevice device) { - removeFdFromAsyncIOCompletion(device.fileDescriptor()); - notifyAsyncIOTask(); - } + void removeFromAsyncIOCompletion(LinuxUsbDevice device) { + int fd = device.fileDescriptor(); - private synchronized void removeFdFromAsyncIOCompletion(int fd) { - // copy file descriptor (except the device's) into new array - var n = asyncFds.length; - if (n == 0) - return; - - var fds = new int[n - 1]; - var tgt = 0; - for (var asyncFd : asyncFds) { - if (asyncFd != fd) { - if (tgt == n) - return; - fds[tgt] = asyncFd; - tgt += 1; - } + // remove file descriptor from epoll + synchronized (this) { + EPoll.removeFileDescriptor(epollFd, fd); } - // make new array to active one - asyncFds = fds; + // reap outstanding URBs + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + var urbPointerHolder = arena.allocate(ADDRESS); + reapURBs(fd, urbPointerHolder, errorState); + } + + // reclaim stale URBs + var staleTransfers = new ArrayList(); + synchronized (this) { + transfersByURB.entrySet().removeIf(e -> { + var urb = e.getKey(); + var isMatch = usbdevfs_urb.usercontext(urb).address() == fd; + if (isMatch) { + var transfer = e.getValue(); + transfer.urb = null; + transfer.setResultCode(ENODEV()); + transfer.setResultSize(0); + availableURBs.add(urb); + staleTransfers.add(transfer); + } + return isMatch; + }); + } + completeTransfers(staleTransfers); } - synchronized void submitTransfer(LinuxUSBDevice device, int endpointAddress, USBTransferType transferType, LinuxTransfer transfer) { + synchronized void submitTransfer(LinuxUsbDevice device, int endpointAddress, UsbTransferType transferType, LinuxTransfer transfer) { + if (taskTerminated) + throw new UsbException("USB async IO background thread has terminated due to an unrecoverable error; " + + "USB transfers are no longer possible"); - addURB(transfer); + linkToUrb(transfer); var urb = transfer.urb; - usbdevfs_urb.type$set(urb, (byte) urbTransferType(transferType)); - usbdevfs_urb.endpoint$set(urb, (byte) endpointAddress); - usbdevfs_urb.buffer$set(urb, transfer.data()); - usbdevfs_urb.buffer_length$set(urb, transfer.dataSize()); - usbdevfs_urb.usercontext$set(urb, MemorySegment.ofAddress(device.fileDescriptor())); + usbdevfs_urb.type(urb, (byte) urbTransferType(transferType)); + usbdevfs_urb.endpoint(urb, (byte) endpointAddress); + usbdevfs_urb.buffer(urb, transfer.data()); + usbdevfs_urb.buffer_length(urb, transfer.dataSize()); + usbdevfs_urb.usercontext(urb, MemorySegment.ofAddress(device.fileDescriptor())); try (var arena = Arena.ofConfined()) { var errorState = allocateErrorState(arena); if (IO.ioctl(device.fileDescriptor(), SUBMITURB, urb, errorState) < 0) { + submissionFailed(transfer); var action = endpointAddress >= 128 ? "reading from" : "writing to"; var endpoint = endpointAddress == 0 ? "control endpoint" : String.format("endpoint %d", endpointAddress); throwLastError(errorState, "error occurred while %s %s", action, endpoint); @@ -258,7 +289,24 @@ synchronized void submitTransfer(LinuxUSBDevice device, int endpointAddress, USB } } - private static int urbTransferType(USBTransferType transferType) { + /** + * Undoes the registration performed by {@link #linkToUrb(LinuxTransfer)}. + *

+ * Must be called if the {@code SUBMITURB} ioctl for a linked transfer fails. In that + * case, the kernel has not queued the URB and it will never be reaped, so its map + * entry would leak and the URB would never return to the pool unless they are + * cleaned up here. + *

+ * + * @param transfer transfer whose submission failed + */ + private void submissionFailed(LinuxTransfer transfer) { + transfersByURB.remove(transfer.urb); + availableURBs.add(transfer.urb); + transfer.urb = null; + } + + private static int urbTransferType(UsbTransferType transferType) { return switch (transferType) { case BULK -> USBDEVFS_URB_TYPE_BULK(); case INTERRUPT -> USBDEVFS_URB_TYPE_INTERRUPT(); @@ -267,7 +315,15 @@ private static int urbTransferType(USBTransferType transferType) { }; } - private void addURB(LinuxTransfer transfer) { + /** + * Links the specified transfer instance to a URB. + *

+ * The transfer is assigned a URB instance, and a list + * of associations from URB to transfer is maintained. + *

+ * @param transfer the transfer to assign a URB. + */ + private void linkToUrb(LinuxTransfer transfer) { MemorySegment urb; var size = availableURBs.size(); if (size > 0) { @@ -280,50 +336,59 @@ private void addURB(LinuxTransfer transfer) { transfersByURB.put(urb, transfer); } + /** + * Gets the transfer associated with the specified URB and adds the result. + *

+ * The URB is returned into the list of URBs available for further transfers. + *

+ * + * @param urb URB instance + * @return transfer associated with the URB + */ @SuppressWarnings("java:S2259") - private synchronized LinuxTransfer getTransferResult(MemorySegment urb) { + private synchronized LinuxTransfer getTransferWithResult(MemorySegment urb) { var transfer = transfersByURB.remove(urb); if (transfer == null) throwException("internal error (unknown URB)"); - transfer.setResultCode(-usbdevfs_urb.status$get(transfer.urb)); - transfer.setResultSize(usbdevfs_urb.actual_length$get(transfer.urb)); + transfer.setResultCode(-usbdevfs_urb.status(transfer.urb)); + transfer.setResultSize(usbdevfs_urb.actual_length(transfer.urb)); availableURBs.add(transfer.urb); transfer.urb = null; + return transfer; } @SuppressWarnings("java:S1066") - synchronized void abortTransfers(LinuxUSBDevice device, byte endpointAddress) { + synchronized void abortTransfers(LinuxUsbDevice device, byte endpointAddress) { var fd = device.fileDescriptor(); try (var arena = Arena.ofConfined()) { var errorState = allocateErrorState(arena); // iterate all URBs and discard the ones for the specified endpoint - for (var urb : transfersByURB.keySet()) { - if (fd != (int) usbdevfs_urb.usercontext$get(urb).address() - || endpointAddress != usbdevfs_urb.endpoint$get(urb)) - continue; - - if (IO.ioctl(fd, DISCARDURB, urb, errorState) < 0) { - // ignore EINVAL; it occurs if the URB has completed at the same time - if (Linux.getErrno(errorState) != errno.EINVAL()) - throwLastError(errorState, "error occurred while aborting transfer"); - } - } + transfersByURB.keySet().stream() + .filter(urb -> + usbdevfs_urb.usercontext(urb).address() == fd + && usbdevfs_urb.endpoint(urb) == endpointAddress) + .forEach(urb -> { + if (IO.ioctl(fd, DISCARDURB, urb, errorState) < 0) { + // ignore EINVAL; it occurs if the URB has completed at the same time + if (Linux.getErrno(errorState) != errno.EINVAL()) + throwLastError(errorState, "error occurred while aborting transfer"); + } + } + ); } } private void startAsyncIOTask() { try (var arena = Arena.ofConfined()) { var errorState = allocateErrorState(arena); - asyncIOWakeUpEventFd = IO.eventfd(0, 0, errorState); - if (asyncIOWakeUpEventFd == -1) { - asyncIOWakeUpEventFd = 0; - throwLastError(errorState, "internal error (eventfd)"); - } + epollFd = epoll_create1(FD_CLOEXEC(), errorState); + if (epollFd < 0) + throwLastError(errorState, "internal error (epoll_create)"); } // start background thread for handling IO completion diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointInputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointInputStream.java index 9d1f7ce0..2f48a0e6 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointInputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointInputStream.java @@ -7,18 +7,18 @@ package net.codecrete.usb.linux; -import net.codecrete.usb.USBDirection; +import net.codecrete.usb.UsbDirection; import net.codecrete.usb.common.EndpointInputStream; import net.codecrete.usb.common.Transfer; public class LinuxEndpointInputStream extends EndpointInputStream { - LinuxEndpointInputStream(LinuxUSBDevice device, int endpointNumber, int bufferSize) { + LinuxEndpointInputStream(LinuxUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferIn(Transfer transfer) { - ((LinuxUSBDevice) device).submitTransfer(USBDirection.IN, endpointNumber, (LinuxTransfer) transfer); + ((LinuxUsbDevice) device).submitTransfer(UsbDirection.IN, endpointNumber, (LinuxTransfer) transfer); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointOutputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointOutputStream.java index ab5b997d..024b8da0 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointOutputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxEndpointOutputStream.java @@ -7,18 +7,18 @@ package net.codecrete.usb.linux; -import net.codecrete.usb.USBDirection; +import net.codecrete.usb.UsbDirection; import net.codecrete.usb.common.EndpointOutputStream; import net.codecrete.usb.common.Transfer; public class LinuxEndpointOutputStream extends EndpointOutputStream { - LinuxEndpointOutputStream(LinuxUSBDevice device, int endpointNumber, int bufferSize) { + LinuxEndpointOutputStream(LinuxUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferOut(Transfer transfer) { - ((LinuxUSBDevice) device).submitTransfer(USBDirection.OUT, endpointNumber, (LinuxTransfer) transfer); + ((LinuxUsbDevice) device).submitTransfer(UsbDirection.OUT, endpointNumber, (LinuxTransfer) transfer); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDevice.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDevice.java similarity index 57% rename from java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDevice.java rename to java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDevice.java index 897d3c16..d0c87f09 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDevice.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDevice.java @@ -7,13 +7,13 @@ package net.codecrete.usb.linux; -import net.codecrete.usb.USBControlTransfer; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBException; -import net.codecrete.usb.USBTransferType; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbTransferType; import net.codecrete.usb.common.Transfer; -import net.codecrete.usb.common.USBDeviceImpl; -import net.codecrete.usb.common.USBInterfaceImpl; +import net.codecrete.usb.common.UsbDeviceImpl; +import net.codecrete.usb.common.UsbInterfaceImpl; import net.codecrete.usb.linux.gen.fcntl.fcntl; import net.codecrete.usb.linux.gen.unistd.unistd; import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevfs_disconnect_claim; @@ -22,6 +22,7 @@ import net.codecrete.usb.linux.gen.usbdevice_fs.usbdevice_fs; import net.codecrete.usb.usbstandard.DeviceDescriptor; import net.codecrete.usb.usbstandard.SetupPacket; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.InputStream; @@ -34,22 +35,22 @@ import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; import static net.codecrete.usb.linux.Linux.allocateErrorState; -import static net.codecrete.usb.linux.LinuxUSBException.throwException; -import static net.codecrete.usb.linux.LinuxUSBException.throwLastError; +import static net.codecrete.usb.linux.LinuxUsbException.throwException; +import static net.codecrete.usb.linux.LinuxUsbException.throwLastError; @SuppressWarnings("java:S2160") -public class LinuxUSBDevice extends USBDeviceImpl { +public class LinuxUsbDevice extends UsbDeviceImpl { - @SuppressWarnings("resource") - private static final MemorySegment DRIVER_NAME_USBFS = Arena.global().allocateUtf8String("usbfs"); + private static final MemorySegment DRIVER_NAME_USBFS = Arena.global().allocateFrom("usbfs"); - private int fd = -1; + // volatile: written under the device monitor, read unlocked via isOpened() + private volatile int fd = -1; private final LinuxAsyncTask asyncTask; private boolean detachDrivers = false; - LinuxUSBDevice(Object id, int vendorId, int productId) { + LinuxUsbDevice(Object id, int vendorId, int productId) { super(id, vendorId, productId); asyncTask = LinuxAsyncTask.INSTANCE; loadDescription((String) id); @@ -60,7 +61,7 @@ private void loadDescription(String path) { try { descriptors = Files.readAllBytes(Path.of(path)); } catch (IOException e) { - throw new USBException("reading configuration descriptor failed", e); + throw new UsbException("reading configuration descriptor failed", e); } // `descriptors` contains the device descriptor followed by the configuration descriptor @@ -71,31 +72,28 @@ private void loadDescription(String path) { } @Override - public void detachStandardDrivers() { - if (isOpen()) - throwException("detachStandardDrivers() must not be called while the device is open"); + public synchronized void detachStandardDrivers() { + checkIsClosed("detachStandardDrivers() must not be called while the device is open"); detachDrivers = true; } @Override - public void attachStandardDrivers() { - if (isOpen()) - throwException("attachStandardDrivers() must not be called while the device is open"); + public synchronized void attachStandardDrivers() { + checkIsClosed("attachStandardDrivers() must not be called while the device is open"); detachDrivers = false; } @Override - public boolean isOpen() { + public boolean isOpened() { return fd != -1; } @Override public synchronized void open() { - if (isOpen()) - throwException("device is already open"); + checkIsClosed("device is already open"); try (var arena = Arena.ofConfined()) { - var pathUtf8 = arena.allocateUtf8String(uniqueDeviceId.toString()); + var pathUtf8 = arena.allocateFrom(uniqueDeviceId.toString()); var errorState = allocateErrorState(arena); fd = IO.open(pathUtf8, fcntl.O_RDWR() | fcntl.O_CLOEXEC(), errorState); if (fd == -1) @@ -106,13 +104,13 @@ public synchronized void open() { @Override public synchronized void close() { - if (!isOpen()) + if (!isOpened()) return; asyncTask.removeFromAsyncIOCompletion(this); for (var intf : interfaceList) - ((USBInterfaceImpl) intf).setClaimed(false); + ((UsbInterfaceImpl) intf).setClaimed(false); unistd.close(fd); fd = -1; @@ -134,15 +132,16 @@ public synchronized void claimInterface(int interfaceNumber) { if (detachDrivers) { // claim interface (detaching kernel driver) var disconnectClaim = usbdevfs_disconnect_claim.allocate(arena); - usbdevfs_disconnect_claim.interface_$set(disconnectClaim, interfaceNumber); - usbdevfs_disconnect_claim.flags$set(disconnectClaim, usbdevice_fs.USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER()); - usbdevfs_disconnect_claim.driver$slice(disconnectClaim).copyFrom(DRIVER_NAME_USBFS); - ret = IO.ioctl(fd, USBDevFS.DISCONNECT_CLAIM, disconnectClaim, errorState); + usbdevfs_disconnect_claim.interface_(disconnectClaim, interfaceNumber); + usbdevfs_disconnect_claim.flags(disconnectClaim, usbdevice_fs.USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER()); + usbdevfs_disconnect_claim.driver(disconnectClaim).copyFrom(DRIVER_NAME_USBFS); + ret = IO.ioctl(fd, UsbDevFS.DISCONNECT_CLAIM, disconnectClaim, errorState); } else { // claim interface (without detaching kernel driver) - var intfNumSegment = arena.allocate(JAVA_INT, interfaceNumber); - ret = IO.ioctl(fd, USBDevFS.CLAIMINTERFACE, intfNumSegment, errorState); + var intfNumSegment = arena.allocate(JAVA_INT); + intfNumSegment.setAtIndex(JAVA_INT, 0, interfaceNumber); + ret = IO.ioctl(fd, UsbDevFS.CLAIMINTERFACE, intfNumSegment, errorState); } if (ret != 0) @@ -160,16 +159,13 @@ public synchronized void selectAlternateSetting(int interfaceNumber, int alterna // check alternate setting var altSetting = intf.getAlternate(alternateNumber); - if (altSetting == null) - throwException("interface %d does not have an alternate interface setting %d", interfaceNumber, - alternateNumber); try (var arena = Arena.ofConfined()) { var setIntfSegment = usbdevfs_setinterface.allocate(arena); - usbdevfs_setinterface.interface_$set(setIntfSegment, interfaceNumber); - usbdevfs_setinterface.altsetting$set(setIntfSegment, alternateNumber); + usbdevfs_setinterface.interface_(setIntfSegment, interfaceNumber); + usbdevfs_setinterface.altsetting(setIntfSegment, alternateNumber); var errorState = allocateErrorState(arena); - var ret = IO.ioctl(fd, USBDevFS.SETINTERFACE, setIntfSegment, errorState); + var ret = IO.ioctl(fd, UsbDevFS.SETINTERFACE, setIntfSegment, errorState); if (ret != 0) throwLastError(errorState, "setting alternate interface failed"); } @@ -183,9 +179,10 @@ public synchronized void releaseInterface(int interfaceNumber) { getInterfaceWithCheck(interfaceNumber, true); try (var arena = Arena.ofConfined()) { - var intfNumSegment = arena.allocate(JAVA_INT, interfaceNumber); + var intfNumSegment = arena.allocate(JAVA_INT); + intfNumSegment.setAtIndex(JAVA_INT, 0, interfaceNumber); var errorState = allocateErrorState(arena); - var ret = IO.ioctl(fd, USBDevFS.RELEASEINTERFACE, intfNumSegment, errorState); + var ret = IO.ioctl(fd, UsbDevFS.RELEASEINTERFACE, intfNumSegment, errorState); if (ret != 0) throwLastError(errorState, "releasing USB interface failed"); @@ -194,37 +191,37 @@ public synchronized void releaseInterface(int interfaceNumber) { if (detachDrivers) { // reattach kernel driver var request = usbdevfs_ioctl.allocate(arena); - usbdevfs_ioctl.ifno$set(request, interfaceNumber); - usbdevfs_ioctl.ioctl_code$set(request, USBDevFS.CONNECT); - usbdevfs_ioctl.data$set(request, MemorySegment.NULL); - IO.ioctl(fd, USBDevFS.IOCTL, request, errorState); + usbdevfs_ioctl.ifno(request, interfaceNumber); + usbdevfs_ioctl.ioctl_code(request, UsbDevFS.CONNECT); + usbdevfs_ioctl.data(request, MemorySegment.NULL); + IO.ioctl(fd, UsbDevFS.IOCTL, request, errorState); } } } @Override - public void controlTransferOut(USBControlTransfer setup, byte[] data) { + public void controlTransferOut(@NotNull UsbControlTransfer setup, byte[] data) { try (var arena = Arena.ofConfined()) { var dataLength = data != null ? data.length : 0; - var transfer = createSyncCtrlTransfer(arena, USBDirection.OUT, setup, dataLength); + var transfer = createSyncCtrlTransfer(arena, UsbDirection.OUT, setup, dataLength); if (dataLength != 0) transfer.data().asSlice(8).copyFrom(MemorySegment.ofArray(data)); synchronized (transfer) { - submitTransfer(USBDirection.OUT, 0, transfer); - waitForTransfer(transfer, 0, USBDirection.OUT, 0); + submitTransfer(UsbDirection.OUT, 0, transfer); + waitForTransfer(transfer, 0, UsbDirection.OUT, 0); } } } @Override - public byte[] controlTransferIn(USBControlTransfer setup, int length) { + public byte @NotNull [] controlTransferIn(@NotNull UsbControlTransfer setup, int length) { try (var arena = Arena.ofConfined()) { - var transfer = createSyncCtrlTransfer(arena, USBDirection.IN, setup, length); + var transfer = createSyncCtrlTransfer(arena, UsbDirection.IN, setup, length); synchronized (transfer) { - submitTransfer(USBDirection.IN, 0, transfer); - waitForTransfer(transfer, 0, USBDirection.IN, 0); + submitTransfer(UsbDirection.IN, 0, transfer); + waitForTransfer(transfer, 0, UsbDirection.IN, 0); } return transfer.data().asSlice(8, transfer.resultSize()).toArray(JAVA_BYTE); @@ -240,10 +237,10 @@ public byte[] controlTransferIn(USBControlTransfer setup, int length) { * @param dataLength data length (in addition to setup data) * @return transfer object */ - private LinuxTransfer createSyncCtrlTransfer(Arena arena, USBDirection direction, USBControlTransfer setup, + private LinuxTransfer createSyncCtrlTransfer(Arena arena, UsbDirection direction, UsbControlTransfer setup, int dataLength) { var bmRequest = - (direction == USBDirection.IN ? 0x80 : 0) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); + (direction == UsbDirection.IN ? 0x80 : 0) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); var buffer = arena.allocate(8L + dataLength, 8); var setupPacket = new SetupPacket(buffer); setupPacket.setRequestType(bmRequest); @@ -256,40 +253,42 @@ private LinuxTransfer createSyncCtrlTransfer(Arena arena, USBDirection direction transfer.setData(buffer); transfer.setDataSize((int) buffer.byteSize()); transfer.setResultSize(-1); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); return transfer; } @Override - public void transferOut(int endpointNumber, byte[] data, int offset, int length, int timeout) { - try (var arena = Arena.ofConfined()) { - var buffer = arena.allocate(length); - buffer.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); - var transfer = createSyncTransfer(buffer); - - synchronized (transfer) { - submitTransfer(USBDirection.OUT, endpointNumber, transfer); - waitForTransfer(transfer, timeout, USBDirection.OUT, endpointNumber); - } + public void transferOut(int endpointNumber, byte @NotNull [] data, int offset, int length, int timeout) { + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var buffer = arena.allocate(length); + buffer.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); + var transfer = createSyncTransfer(buffer); + + synchronized (transfer) { + submitTransfer(UsbDirection.OUT, endpointNumber, transfer); + waitForTransfer(transfer, timeout, UsbDirection.OUT, endpointNumber); } } @Override - public byte[] transferIn(int endpointNumber, int timeout) { - var endpoint = getEndpoint(USBDirection.IN, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - - try (var arena = Arena.ofConfined()) { - var buffer = arena.allocate(endpoint.packetSize()); - var transfer = createSyncTransfer(buffer); - - synchronized (transfer) { - submitTransfer(USBDirection.IN, endpointNumber, transfer); - waitForTransfer(transfer, timeout, USBDirection.IN, endpointNumber); - } - - return buffer.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); + public byte @NotNull [] transferIn(int endpointNumber, int timeout) { + var endpoint = getEndpoint(UsbDirection.IN, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var buffer = arena.allocate(endpoint.packetSize()); + var transfer = createSyncTransfer(buffer); + + synchronized (transfer) { + submitTransfer(UsbDirection.IN, endpointNumber, transfer); + waitForTransfer(transfer, timeout, UsbDirection.IN, endpointNumber); } + + return buffer.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); } private LinuxTransfer createSyncTransfer(MemorySegment data) { @@ -297,16 +296,16 @@ private LinuxTransfer createSyncTransfer(MemorySegment data) { transfer.setData(data); transfer.setDataSize((int) data.byteSize()); transfer.setResultSize(-1); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); return transfer; } - synchronized void submitTransfer(USBDirection direction, int endpointNumber, LinuxTransfer transfer) { + synchronized void submitTransfer(UsbDirection direction, int endpointNumber, LinuxTransfer transfer) { if (endpointNumber != 0) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); asyncTask.submitTransfer(this, endpoint.endpointAddress(), endpoint.transferType(), transfer); } else { - asyncTask.submitTransfer(this, 0, USBTransferType.CONTROL, transfer); + asyncTask.submitTransfer(this, 0, UsbTransferType.CONTROL, transfer); } } @@ -321,37 +320,38 @@ protected void throwOSException(int errorCode, String message, Object... args) { } @Override - public void clearHalt(USBDirection direction, int endpointNumber) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); + public void clearHalt(UsbDirection direction, int endpointNumber) { + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); try (var arena = Arena.ofConfined()) { - var endpointAddrSegment = arena.allocate(JAVA_INT, endpoint.endpointAddress() & 0xff); + var endpointAddrSegment = arena.allocate(JAVA_INT); + endpointAddrSegment.setAtIndex(JAVA_INT, 0, endpoint.endpointAddress() & 0xff); var errorState = allocateErrorState(arena); - var res = IO.ioctl(fd, USBDevFS.CLEAR_HALT, endpointAddrSegment, errorState); + var res = IO.ioctl(fd, UsbDevFS.CLEAR_HALT, endpointAddrSegment, errorState); if (res < 0) throwLastError(errorState, "clearing halt failed"); } } @Override - public synchronized void abortTransfers(USBDirection direction, int endpointNumber) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); + public synchronized void abortTransfers(UsbDirection direction, int endpointNumber) { + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); asyncTask.abortTransfers(this, endpoint.endpointAddress()); } @Override - public synchronized InputStream openInputStream(int endpointNumber, int bufferSize) { + public synchronized @NotNull InputStream openInputStream(int endpointNumber, int bufferSize) { // check that endpoint number is valid - getEndpoint(USBDirection.IN, endpointNumber, USBTransferType.BULK, null); + getEndpoint(UsbDirection.IN, endpointNumber, UsbTransferType.BULK, null); return new LinuxEndpointInputStream(this, endpointNumber, bufferSize); } @Override - public synchronized OutputStream openOutputStream(int endpointNumber, int bufferSize) { + public synchronized @NotNull OutputStream openOutputStream(int endpointNumber, int bufferSize) { // check that endpoint number is valid - getEndpoint(USBDirection.OUT, endpointNumber, USBTransferType.BULK, null); + getEndpoint(UsbDirection.OUT, endpointNumber, UsbTransferType.BULK, null); return new LinuxEndpointOutputStream(this, endpointNumber, bufferSize); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDeviceRegistry.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDeviceRegistry.java similarity index 62% rename from java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDeviceRegistry.java rename to java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDeviceRegistry.java index ec12e75d..6c39abe9 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBDeviceRegistry.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbDeviceRegistry.java @@ -7,11 +7,9 @@ package net.codecrete.usb.linux; -import net.codecrete.usb.USBDevice; +import net.codecrete.usb.UsbDevice; import net.codecrete.usb.common.ScopeCleanup; -import net.codecrete.usb.common.USBDeviceRegistry; -import net.codecrete.usb.linux.gen.poll.poll; -import net.codecrete.usb.linux.gen.poll.pollfd; +import net.codecrete.usb.common.UsbDeviceRegistry; import net.codecrete.usb.linux.gen.udev.udev; import java.lang.foreign.Arena; @@ -20,14 +18,22 @@ import java.util.List; import static java.lang.System.Logger.Level.INFO; -import static net.codecrete.usb.linux.LinuxUSBException.throwException; +import static java.lang.foreign.MemorySegment.NULL; +import static net.codecrete.usb.linux.EPoll.epoll_create1; +import static net.codecrete.usb.linux.EPoll.epoll_wait; +import static net.codecrete.usb.linux.Linux.allocateErrorState; +import static net.codecrete.usb.linux.LinuxUsbException.throwException; +import static net.codecrete.usb.linux.LinuxUsbException.throwLastError; +import static net.codecrete.usb.linux.gen.epoll.epoll.EPOLLIN; +import static net.codecrete.usb.linux.gen.errno.errno.EINTR; +import static net.codecrete.usb.linux.gen.fcntl.fcntl.FD_CLOEXEC; /** * Linux implementation of USB device registry. */ -public class LinuxUSBDeviceRegistry extends USBDeviceRegistry { +public class LinuxUsbDeviceRegistry extends UsbDeviceRegistry { - private static final System.Logger LOG = System.getLogger(LinuxUSBDeviceRegistry.class.getName()); + private static final System.Logger LOG = System.getLogger(LinuxUsbDeviceRegistry.class.getName()); private static final MemorySegment SUBSYSTEM_USB; private static final MemorySegment MONITOR_NAME; @@ -39,28 +45,25 @@ public class LinuxUSBDeviceRegistry extends USBDeviceRegistry { private static final MemorySegment ATTR_PRODUCT; private static final MemorySegment ATTR_SERIAL; + private MemorySegment monitor; + private int monitorFd; + static { - @SuppressWarnings("resource") var global = Arena.global(); - SUBSYSTEM_USB = global.allocateUtf8String("usb"); - MONITOR_NAME = global.allocateUtf8String("udev"); - DEVTYPE_USB_DEVICE = global.allocateUtf8String("usb_device"); + SUBSYSTEM_USB = global.allocateFrom("usb"); + MONITOR_NAME = global.allocateFrom("udev"); + DEVTYPE_USB_DEVICE = global.allocateFrom("usb_device"); - ATTR_ID_VENDOR = global.allocateUtf8String("idVendor"); - ATTR_ID_PRODUCT = global.allocateUtf8String("idProduct"); - ATTR_MANUFACTURER = global.allocateUtf8String("manufacturer"); - ATTR_PRODUCT = global.allocateUtf8String("product"); - ATTR_SERIAL = global.allocateUtf8String("serial"); + ATTR_ID_VENDOR = global.allocateFrom("idVendor"); + ATTR_ID_PRODUCT = global.allocateFrom("idProduct"); + ATTR_MANUFACTURER = global.allocateFrom("manufacturer"); + ATTR_PRODUCT = global.allocateFrom("product"); + ATTR_SERIAL = global.allocateFrom("serial"); } - @SuppressWarnings({"java:S1181", "java:S2189"}) - @Override - protected void monitorDevices() { - - int fd; - MemorySegment monitor; - + @SuppressWarnings("java:S1181") + private boolean setupMonitor() { try { // setup udev monitor var udevInstance = udev.udev_new(); @@ -77,49 +80,74 @@ protected void monitorDevices() { if (udev.udev_monitor_enable_receiving(monitor) < 0) throwException("internal error (udev_monitor_enable_receiving)"); - fd = udev.udev_monitor_get_fd(monitor); - if (fd < 0) + monitorFd = udev.udev_monitor_get_fd(monitor); + if (monitorFd < 0) throwException("internal error (udev_monitor_get_fd)"); // create initial list of devices var deviceList = enumeratePresentDevices(udevInstance); setInitialDeviceList(deviceList); + return true; } catch (Throwable e) { enumerationFailed(e); - return; + return false; } + } - // monitor device changes - //noinspection InfiniteLoopStatement - while (true) { - try (var arena = Arena.ofConfined(); var cleanup = new ScopeCleanup()) { - - // wait for next change - waitForFileDescriptor(fd, arena); + @SuppressWarnings("java:S2189") + @Override + protected void monitorDevices() { + if (!setupMonitor()) + return; - // retrieve change - var udevDevice = udev.udev_monitor_receive_device(monitor); - if (udevDevice == null) - continue; // shouldn't happen + try (var arena = Arena.ofConfined()) { + // create epoll + var errorState = allocateErrorState(arena); + var epfd = epoll_create1(FD_CLOEXEC(), errorState); + if (epfd < 0) + throwLastError(errorState, "internal error (epoll_create)"); + EPoll.addFileDescriptor(epfd, EPOLLIN(), monitorFd); - cleanup.add(() -> udev.udev_device_unref(udevDevice)); + // allocate event (as output for epoll_wait) + var event = arena.allocate(EPoll.EVENT$LAYOUT); - // get details - var action = getDeviceAction(udevDevice); + // monitor device changes + //noinspection InfiniteLoopStatement + while (true) { + try (var cleanup = new ScopeCleanup()) { - if ("add".equals(action)) { - onDeviceConnected(udevDevice); - } else if ("remove".equals(action)) { - onDeviceDisconnected(udevDevice); + // wait for next change + int res = epoll_wait(epfd, event, 1, -1, errorState); + if (res < 0) { + var err = Linux.getErrno(errorState); + if (err == EINTR()) + continue; // continue on interrupt + throwException(err, "internal error (epoll_wait)"); + } + + // retrieve change + var udevDevice = udev.udev_monitor_receive_device(monitor); + if (udevDevice != NULL) { + cleanup.add(() -> udev.udev_device_unref(udevDevice)); + + // get details + var action = getDeviceAction(udevDevice); + + if ("add".equals(action)) { + onDeviceConnected(udevDevice); + } else if ("remove".equals(action)) { + onDeviceDisconnected(udevDevice); + } + } } } } } @SuppressWarnings("java:S135") - private List enumeratePresentDevices(MemorySegment udevInstance) { - List result = new ArrayList<>(); + private List enumeratePresentDevices(MemorySegment udevInstance) { + List result = new ArrayList<>(); try (var outerCleanup = new ScopeCleanup()) { // create device enumerator @@ -181,7 +209,7 @@ private void onDeviceDisconnected(MemorySegment udevDevice) { } /** - * Retrieves the device details and returns a {@code USBDevice} instance. + * Retrieves the device details and returns a {@code UsbDevice} instance. *

* If the device is missing one of vendor ID, product ID or device path, * {@code null} is returned. @@ -191,7 +219,7 @@ private void onDeviceDisconnected(MemorySegment udevDevice) { * @return the device instance */ @SuppressWarnings("java:S106") - private USBDevice getDeviceDetails(MemorySegment udevDevice) { + private UsbDevice getDeviceDetails(MemorySegment udevDevice) { int vendorId = 0; int productId = 0; @@ -215,7 +243,7 @@ private USBDevice getDeviceDetails(MemorySegment udevDevice) { productId = Integer.parseInt(idProduct, 16); // create device instance - var device = new LinuxUSBDevice(devPath, vendorId, productId); + var device = new LinuxUsbDevice(devPath, vendorId, productId); device.setProductStrings(getDeviceAttribute(udevDevice, ATTR_MANUFACTURER), getDeviceAttribute(udevDevice , ATTR_PRODUCT), getDeviceAttribute(udevDevice, ATTR_SERIAL)); @@ -233,30 +261,14 @@ private static String getDeviceAttribute(MemorySegment udevDevice, MemorySegment if (value.address() == 0) return null; - return value.getUtf8String(0); + return value.getString(0); } private static String getDeviceName(MemorySegment udevDevice) { - return udev.udev_device_get_devnode(udevDevice).getUtf8String(0); + return udev.udev_device_get_devnode(udevDevice).getString(0); } private static String getDeviceAction(MemorySegment udevDevice) { - return udev.udev_device_get_action(udevDevice).getUtf8String(0); + return udev.udev_device_get_action(udevDevice).getString(0); } - - /** - * Waits until the specified file descriptor becomes ready for reading. - * - * @param fd the file descriptor - * @param arena an arena for allocating memory - */ - private static void waitForFileDescriptor(int fd, Arena arena) { - var fds = pollfd.allocate(arena); - pollfd.fd$set(fds, fd); - pollfd.events$set(fds, (short) poll.POLLIN()); - int res = poll.poll(fds, 1, -1); - if (res < 0) - throwException("internal error (poll)"); - } - } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBException.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbException.java similarity index 85% rename from java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBException.java rename to java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbException.java index 43924a9a..4f0d95c5 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUSBException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/LinuxUsbException.java @@ -6,8 +6,8 @@ // package net.codecrete.usb.linux; -import net.codecrete.usb.USBException; -import net.codecrete.usb.USBStallException; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbStallException; import net.codecrete.usb.linux.gen.errno.errno; import java.lang.foreign.MemorySegment; @@ -15,7 +15,7 @@ /** * Exception thrown if a Linux specific error occurs. */ -public class LinuxUSBException extends USBException { +public class LinuxUsbException extends UsbException { /** * Creates a new instance. @@ -26,7 +26,7 @@ public class LinuxUSBException extends USBException { * @param message exception message * @param errorCode Linux error code (returned by {@code errno}) */ - public LinuxUSBException(String message, int errorCode) { + public LinuxUsbException(String message, int errorCode) { super(String.format("%s: %s", message, Linux.getErrorMessage(errorCode)), errorCode); } @@ -43,9 +43,9 @@ public LinuxUSBException(String message, int errorCode) { static void throwException(int errorCode, String message, Object... args) { var formattedMessage = String.format(message, args); if (errorCode == errno.EPIPE()) { - throw new USBStallException(formattedMessage); + throw new UsbStallException(formattedMessage); } else { - throw new LinuxUSBException(formattedMessage, errorCode); + throw new LinuxUsbException(formattedMessage, errorCode); } } @@ -56,7 +56,7 @@ static void throwException(int errorCode, String message, Object... args) { * @param args arguments for exception message */ static void throwException(String message, Object... args) { - throw new USBException(String.format(message, args)); + throw new UsbException(String.format(message, args)); } /** diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/USBDevFS.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/UsbDevFS.java similarity index 87% rename from java-does-usb/src/main/java/net/codecrete/usb/linux/USBDevFS.java rename to java-does-usb/src/main/java/net/codecrete/usb/linux/UsbDevFS.java index f3be0b38..15f1d270 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/USBDevFS.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/UsbDevFS.java @@ -14,11 +14,12 @@ * Thus, they cannot be generated using jextract. *

*/ -class USBDevFS { +class UsbDevFS { - private USBDevFS() { + private UsbDevFS() { } + // constants that jextract cannot generate as they are built from function-like macros static final long CLAIMINTERFACE = 0x8004550FL; static final long RELEASEINTERFACE = 0x80045510L; static final long SETINTERFACE = 0x80085504L; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll$shared.java new file mode 100644 index 00000000..5cb27567 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.epoll; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class epoll$shared { + + epoll$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll.java new file mode 100644 index 00000000..22e0cb02 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/epoll/epoll.java @@ -0,0 +1,72 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.epoll; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class epoll extends epoll$shared { + + epoll() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + private static final int EPOLL_CTL_ADD = (int)1L; + /** + * {@snippet lang=c : + * #define EPOLL_CTL_ADD 1 + * } + */ + public static int EPOLL_CTL_ADD() { + return EPOLL_CTL_ADD; + } + private static final int EPOLL_CTL_DEL = (int)2L; + /** + * {@snippet lang=c : + * #define EPOLL_CTL_DEL 2 + * } + */ + public static int EPOLL_CTL_DEL() { + return EPOLL_CTL_DEL; + } + private static final int EPOLLIN = (int)1L; + /** + * {@snippet lang=c : + * enum EPOLL_EVENTS.EPOLLIN = 1 + * } + */ + public static int EPOLLIN() { + return EPOLLIN; + } + private static final int EPOLLOUT = (int)4L; + /** + * {@snippet lang=c : + * enum EPOLL_EVENTS.EPOLLOUT = 4 + * } + */ + public static int EPOLLOUT() { + return EPOLLOUT; + } + private static final int EPOLLWAKEUP = (int)536870912L; + /** + * {@snippet lang=c : + * enum EPOLL_EVENTS.EPOLLWAKEUP = 536870912 + * } + */ + public static int EPOLLWAKEUP() { + return EPOLLWAKEUP; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/RuntimeHelper.java deleted file mode 100644 index f46e44cf..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.errno; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/constants$0.java deleted file mode 100644 index d06cfe72..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/constants$0.java +++ /dev/null @@ -1,11 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.errno; - -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno$shared.java new file mode 100644 index 00000000..499be5f7 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.errno; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class errno$shared { + + errno$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno.java index 5db1b041..d4397f45 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/errno/errno.java @@ -2,51 +2,98 @@ package net.codecrete.usb.linux.gen.errno; -import java.lang.foreign.AddressLayout; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class errno { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class errno extends errno$shared { + + errno() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + private static final int ENOENT = (int)2L; + /** + * {@snippet lang=c : + * #define ENOENT 2 + * } + */ + public static int ENOENT() { + return ENOENT; + } + private static final int EINTR = (int)4L; + /** + * {@snippet lang=c : + * #define EINTR 4 + * } + */ + public static int EINTR() { + return EINTR; + } + private static final int EBADF = (int)9L; + /** + * {@snippet lang=c : + * #define EBADF 9 + * } + */ + public static int EBADF() { + return EBADF; + } + private static final int EAGAIN = (int)11L; + /** + * {@snippet lang=c : * #define EAGAIN 11 * } */ public static int EAGAIN() { - return (int)11L; + return EAGAIN; } + private static final int ENODEV = (int)19L; /** - * {@snippet : + * {@snippet lang=c : * #define ENODEV 19 * } */ public static int ENODEV() { - return (int)19L; + return ENODEV; } + private static final int EINVAL = (int)22L; /** - * {@snippet : + * {@snippet lang=c : * #define EINVAL 22 * } */ public static int EINVAL() { - return (int)22L; + return EINVAL; } + private static final int EPIPE = (int)32L; /** - * {@snippet : + * {@snippet lang=c : * #define EPIPE 32 * } */ public static int EPIPE() { - return (int)32L; + return EPIPE; + } + private static final int ECANCELED = (int)125L; + /** + * {@snippet lang=c : + * #define ECANCELED 125 + * } + */ + public static int ECANCELED() { + return ECANCELED; } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/RuntimeHelper.java deleted file mode 100644 index 6b36ff84..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.fcntl; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/constants$0.java deleted file mode 100644 index 384b1450..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/constants$0.java +++ /dev/null @@ -1,11 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.fcntl; - -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl$shared.java new file mode 100644 index 00000000..0a6ca8e4 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.fcntl; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class fcntl$shared { + + fcntl$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl.java index a6dd2f36..72cbfb53 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/fcntl/fcntl.java @@ -2,35 +2,53 @@ package net.codecrete.usb.linux.gen.fcntl; -import java.lang.foreign.AddressLayout; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class fcntl { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class fcntl extends fcntl$shared { + + fcntl() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + private static final int O_RDWR = (int)2L; /** - * {@snippet : + * {@snippet lang=c : * #define O_RDWR 2 * } */ public static int O_RDWR() { - return (int)2L; + return O_RDWR; } + private static final int FD_CLOEXEC = (int)1L; /** - * {@snippet : + * {@snippet lang=c : + * #define FD_CLOEXEC 1 + * } + */ + public static int FD_CLOEXEC() { + return FD_CLOEXEC; + } + private static final int O_CLOEXEC = (int)524288L; + /** + * {@snippet lang=c : * #define O_CLOEXEC 524288 * } */ public static int O_CLOEXEC() { - return (int)524288L; + return O_CLOEXEC; } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/RuntimeHelper.java deleted file mode 100644 index 5fdcd815..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.poll; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/constants$0.java deleted file mode 100644 index 112fe8b5..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/constants$0.java +++ /dev/null @@ -1,35 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.poll; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withName("fd"), - JAVA_SHORT.withName("events"), - JAVA_SHORT.withName("revents") - ).withName("pollfd"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("fd")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("events")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("revents")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_LONG, - JAVA_INT - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "poll", - constants$0.const$4 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/poll.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/poll.java deleted file mode 100644 index c3002abe..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/poll.java +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.poll; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class poll { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define POLLIN 1 - * } - */ - public static int POLLIN() { - return (int)1L; - } - /** - * {@snippet : - * #define POLLOUT 4 - * } - */ - public static int POLLOUT() { - return (int)4L; - } - /** - * {@snippet : - * #define POLLERR 8 - * } - */ - public static int POLLERR() { - return (int)8L; - } - public static MethodHandle poll$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$5,"poll"); - } - /** - * {@snippet : - * int poll(struct pollfd* __fds, nfds_t __nfds, int __timeout); - * } - */ - public static int poll(MemorySegment __fds, long __nfds, int __timeout) { - var mh$ = poll$MH(); - try { - return (int)mh$.invokeExact(__fds, __nfds, __timeout); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/pollfd.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/pollfd.java deleted file mode 100644 index 6d632aa7..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/poll/pollfd.java +++ /dev/null @@ -1,113 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.poll; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct pollfd { - * int fd; - * short events; - * short revents; - * }; - * } - */ -public class pollfd { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; - } - public static VarHandle fd$VH() { - return constants$0.const$1; - } - /** - * Getter for field: - * {@snippet : - * int fd; - * } - */ - public static int fd$get(MemorySegment seg) { - return (int)constants$0.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * int fd; - * } - */ - public static void fd$set(MemorySegment seg, int x) { - constants$0.const$1.set(seg, x); - } - public static int fd$get(MemorySegment seg, long index) { - return (int)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void fd$set(MemorySegment seg, long index, int x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle events$VH() { - return constants$0.const$2; - } - /** - * Getter for field: - * {@snippet : - * short events; - * } - */ - public static short events$get(MemorySegment seg) { - return (short)constants$0.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * short events; - * } - */ - public static void events$set(MemorySegment seg, short x) { - constants$0.const$2.set(seg, x); - } - public static short events$get(MemorySegment seg, long index) { - return (short)constants$0.const$2.get(seg.asSlice(index*sizeof())); - } - public static void events$set(MemorySegment seg, long index, short x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle revents$VH() { - return constants$0.const$3; - } - /** - * Getter for field: - * {@snippet : - * short revents; - * } - */ - public static short revents$get(MemorySegment seg) { - return (short)constants$0.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * short revents; - * } - */ - public static void revents$set(MemorySegment seg, short x) { - constants$0.const$3.set(seg, x); - } - public static short revents$get(MemorySegment seg, long index) { - return (short)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void revents$set(MemorySegment seg, long index, short x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/RuntimeHelper.java deleted file mode 100644 index e0a365d5..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.string; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/constants$0.java deleted file mode 100644 index bfe9c830..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/constants$0.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.string; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "strerror", - constants$0.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string$shared.java new file mode 100644 index 00000000..824bb277 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.string; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class string$shared { + + string$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string.java index 895d225f..de0e4452 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/string/string.java @@ -2,37 +2,86 @@ package net.codecrete.usb.linux.gen.string; -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class string { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle strerror$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"strerror"); +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class string extends string$shared { + + string() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + + private static class strerror { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + string.C_POINTER, + string.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("strerror"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern char *strerror(int __errnum) + * } + */ + public static FunctionDescriptor strerror$descriptor() { + return strerror.DESC; } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern char *strerror(int __errnum) + * } + */ + public static MethodHandle strerror$handle() { + return strerror.HANDLE; + } + /** - * {@snippet : - * char* strerror(int __errnum); + * Address for: + * {@snippet lang=c : + * extern char *strerror(int __errnum) + * } + */ + public static MemorySegment strerror$address() { + return strerror.ADDR; + } + + /** + * {@snippet lang=c : + * extern char *strerror(int __errnum) * } */ public static MemorySegment strerror(int __errnum) { - var mh$ = strerror$MH(); + var mh$ = strerror.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(__errnum); + if (TRACE_DOWNCALLS) { + traceDowncall("strerror", __errnum); + } + return (MemorySegment)mh$.invokeExact(__errnum); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/RuntimeHelper.java deleted file mode 100644 index c2ccf243..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/RuntimeHelper.java +++ /dev/null @@ -1,228 +0,0 @@ -package net.codecrete.usb.linux.gen.udev; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { -// System.loadLibrary("udev"); -// SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SymbolLookup loaderLookup = SymbolLookup.libraryLookup("libudev.so.1", Arena.global()); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$0.java deleted file mode 100644 index 1017f6fe..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$0.java +++ /dev/null @@ -1,33 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.udev; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "udev_new", - constants$0.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "udev_list_entry_get_next", - constants$0.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "udev_list_entry_get_name", - constants$0.const$2 - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "udev_device_unref", - constants$0.const$2 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$1.java deleted file mode 100644 index 9d318029..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$1.java +++ /dev/null @@ -1,37 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.udev; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "udev_device_new_from_syspath", - constants$1.const$0 - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "udev_device_get_devtype", - constants$0.const$2 - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "udev_device_get_devnode", - constants$0.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "udev_device_get_action", - constants$0.const$2 - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "udev_device_get_sysattr_value", - constants$1.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$2.java deleted file mode 100644 index 88ac3987..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$2.java +++ /dev/null @@ -1,43 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.udev; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - "udev_monitor_new_from_netlink", - constants$1.const$0 - ); - static final FunctionDescriptor const$1 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "udev_monitor_enable_receiving", - constants$2.const$1 - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "udev_monitor_get_fd", - constants$2.const$1 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "udev_monitor_receive_device", - constants$0.const$2 - ); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "udev_monitor_filter_add_match_subsystem_devtype", - constants$2.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$3.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$3.java deleted file mode 100644 index b469b77f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/constants$3.java +++ /dev/null @@ -1,39 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.udev; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$3 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$3() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - "udev_enumerate_unref", - constants$0.const$2 - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "udev_enumerate_new", - constants$0.const$2 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "udev_enumerate_add_match_subsystem", - constants$3.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "udev_enumerate_scan_devices", - constants$2.const$1 - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "udev_enumerate_get_list_entry", - constants$0.const$2 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev$shared.java new file mode 100644 index 00000000..b7958526 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.udev; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class udev$shared { + + udev$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev.java index bcc40cb5..f43a699d 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/udev/udev.java @@ -2,325 +2,1171 @@ package net.codecrete.usb.linux.gen.udev; -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class udev { +import static java.lang.foreign.MemoryLayout.PathElement.*; - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle udev_new$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"udev_new"); +public class udev extends udev$shared { + + udev() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.libraryLookup("libudev.so.1", LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + + + private static class udev_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev *udev_new(void) + * } + */ + public static FunctionDescriptor udev_new$descriptor() { + return udev_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev *udev_new(void) + * } + */ + public static MethodHandle udev_new$handle() { + return udev_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev *udev_new(void) + * } + */ + public static MemorySegment udev_new$address() { + return udev_new.ADDR; } + /** - * {@snippet : - * struct udev* udev_new(); + * {@snippet lang=c : + * struct udev *udev_new(void) * } */ public static MemorySegment udev_new() { - var mh$ = udev_new$MH(); + var mh$ = udev_new.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_new"); + } + return (MemorySegment)mh$.invokeExact(); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_list_entry_get_next$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$3,"udev_list_entry_get_next"); + + private static class udev_list_entry_get_next { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_list_entry_get_next"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) + * } + */ + public static FunctionDescriptor udev_list_entry_get_next$descriptor() { + return udev_list_entry_get_next.DESC; } + /** - * {@snippet : - * struct udev_list_entry* udev_list_entry_get_next(struct udev_list_entry* list_entry); + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) + * } + */ + public static MethodHandle udev_list_entry_get_next$handle() { + return udev_list_entry_get_next.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) + * } + */ + public static MemorySegment udev_list_entry_get_next$address() { + return udev_list_entry_get_next.ADDR; + } + + /** + * {@snippet lang=c : + * struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) * } */ public static MemorySegment udev_list_entry_get_next(MemorySegment list_entry) { - var mh$ = udev_list_entry_get_next$MH(); + var mh$ = udev_list_entry_get_next.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(list_entry); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_list_entry_get_next", list_entry); + } + return (MemorySegment)mh$.invokeExact(list_entry); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_list_entry_get_name$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$4,"udev_list_entry_get_name"); + + private static class udev_list_entry_get_name { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_list_entry_get_name"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) + * } + */ + public static FunctionDescriptor udev_list_entry_get_name$descriptor() { + return udev_list_entry_get_name.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) + * } + */ + public static MethodHandle udev_list_entry_get_name$handle() { + return udev_list_entry_get_name.HANDLE; } + /** - * {@snippet : - * char* udev_list_entry_get_name(struct udev_list_entry* list_entry); + * Address for: + * {@snippet lang=c : + * const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) + * } + */ + public static MemorySegment udev_list_entry_get_name$address() { + return udev_list_entry_get_name.ADDR; + } + + /** + * {@snippet lang=c : + * const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) * } */ public static MemorySegment udev_list_entry_get_name(MemorySegment list_entry) { - var mh$ = udev_list_entry_get_name$MH(); + var mh$ = udev_list_entry_get_name.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(list_entry); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_list_entry_get_name", list_entry); + } + return (MemorySegment)mh$.invokeExact(list_entry); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_unref$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$5,"udev_device_unref"); + + private static class udev_device_unref { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_unref"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_device *udev_device_unref(struct udev_device *udev_device) + * } + */ + public static FunctionDescriptor udev_device_unref$descriptor() { + return udev_device_unref.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_device *udev_device_unref(struct udev_device *udev_device) + * } + */ + public static MethodHandle udev_device_unref$handle() { + return udev_device_unref.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_device *udev_device_unref(struct udev_device *udev_device) + * } + */ + public static MemorySegment udev_device_unref$address() { + return udev_device_unref.ADDR; } + /** - * {@snippet : - * struct udev_device* udev_device_unref(struct udev_device* udev_device); + * {@snippet lang=c : + * struct udev_device *udev_device_unref(struct udev_device *udev_device) * } */ public static MemorySegment udev_device_unref(MemorySegment udev_device) { - var mh$ = udev_device_unref$MH(); + var mh$ = udev_device_unref.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_device); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_unref", udev_device); + } + return (MemorySegment)mh$.invokeExact(udev_device); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_new_from_syspath$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$1,"udev_device_new_from_syspath"); + + private static class udev_device_new_from_syspath { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_new_from_syspath"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) + * } + */ + public static FunctionDescriptor udev_device_new_from_syspath$descriptor() { + return udev_device_new_from_syspath.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) + * } + */ + public static MethodHandle udev_device_new_from_syspath$handle() { + return udev_device_new_from_syspath.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) + * } + */ + public static MemorySegment udev_device_new_from_syspath$address() { + return udev_device_new_from_syspath.ADDR; } + /** - * {@snippet : - * struct udev_device* udev_device_new_from_syspath(struct udev* udev, char* syspath); + * {@snippet lang=c : + * struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) * } */ public static MemorySegment udev_device_new_from_syspath(MemorySegment udev, MemorySegment syspath) { - var mh$ = udev_device_new_from_syspath$MH(); + var mh$ = udev_device_new_from_syspath.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev, syspath); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_new_from_syspath", udev, syspath); + } + return (MemorySegment)mh$.invokeExact(udev, syspath); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_get_devtype$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$2,"udev_device_get_devtype"); + + private static class udev_device_get_devtype { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_get_devtype"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * const char *udev_device_get_devtype(struct udev_device *udev_device) + * } + */ + public static FunctionDescriptor udev_device_get_devtype$descriptor() { + return udev_device_get_devtype.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * const char *udev_device_get_devtype(struct udev_device *udev_device) + * } + */ + public static MethodHandle udev_device_get_devtype$handle() { + return udev_device_get_devtype.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * const char *udev_device_get_devtype(struct udev_device *udev_device) + * } + */ + public static MemorySegment udev_device_get_devtype$address() { + return udev_device_get_devtype.ADDR; } + /** - * {@snippet : - * char* udev_device_get_devtype(struct udev_device* udev_device); + * {@snippet lang=c : + * const char *udev_device_get_devtype(struct udev_device *udev_device) * } */ public static MemorySegment udev_device_get_devtype(MemorySegment udev_device) { - var mh$ = udev_device_get_devtype$MH(); + var mh$ = udev_device_get_devtype.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_device); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_get_devtype", udev_device); + } + return (MemorySegment)mh$.invokeExact(udev_device); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_get_devnode$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$3,"udev_device_get_devnode"); + + private static class udev_device_get_devnode { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_get_devnode"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * const char *udev_device_get_devnode(struct udev_device *udev_device) + * } + */ + public static FunctionDescriptor udev_device_get_devnode$descriptor() { + return udev_device_get_devnode.DESC; } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * const char *udev_device_get_devnode(struct udev_device *udev_device) + * } + */ + public static MethodHandle udev_device_get_devnode$handle() { + return udev_device_get_devnode.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * const char *udev_device_get_devnode(struct udev_device *udev_device) + * } + */ + public static MemorySegment udev_device_get_devnode$address() { + return udev_device_get_devnode.ADDR; + } + /** - * {@snippet : - * char* udev_device_get_devnode(struct udev_device* udev_device); + * {@snippet lang=c : + * const char *udev_device_get_devnode(struct udev_device *udev_device) * } */ public static MemorySegment udev_device_get_devnode(MemorySegment udev_device) { - var mh$ = udev_device_get_devnode$MH(); + var mh$ = udev_device_get_devnode.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_device); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_get_devnode", udev_device); + } + return (MemorySegment)mh$.invokeExact(udev_device); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_get_action$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$4,"udev_device_get_action"); + + private static class udev_device_get_action { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_get_action"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * const char *udev_device_get_action(struct udev_device *udev_device) + * } + */ + public static FunctionDescriptor udev_device_get_action$descriptor() { + return udev_device_get_action.DESC; } + /** - * {@snippet : - * char* udev_device_get_action(struct udev_device* udev_device); + * Downcall method handle for: + * {@snippet lang=c : + * const char *udev_device_get_action(struct udev_device *udev_device) + * } + */ + public static MethodHandle udev_device_get_action$handle() { + return udev_device_get_action.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * const char *udev_device_get_action(struct udev_device *udev_device) + * } + */ + public static MemorySegment udev_device_get_action$address() { + return udev_device_get_action.ADDR; + } + + /** + * {@snippet lang=c : + * const char *udev_device_get_action(struct udev_device *udev_device) * } */ public static MemorySegment udev_device_get_action(MemorySegment udev_device) { - var mh$ = udev_device_get_action$MH(); + var mh$ = udev_device_get_action.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_device); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_get_action", udev_device); + } + return (MemorySegment)mh$.invokeExact(udev_device); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_device_get_sysattr_value$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$5,"udev_device_get_sysattr_value"); + + private static class udev_device_get_sysattr_value { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_device_get_sysattr_value"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) + * } + */ + public static FunctionDescriptor udev_device_get_sysattr_value$descriptor() { + return udev_device_get_sysattr_value.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) + * } + */ + public static MethodHandle udev_device_get_sysattr_value$handle() { + return udev_device_get_sysattr_value.HANDLE; } + /** - * {@snippet : - * char* udev_device_get_sysattr_value(struct udev_device* udev_device, char* sysattr); + * Address for: + * {@snippet lang=c : + * const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) + * } + */ + public static MemorySegment udev_device_get_sysattr_value$address() { + return udev_device_get_sysattr_value.ADDR; + } + + /** + * {@snippet lang=c : + * const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) * } */ public static MemorySegment udev_device_get_sysattr_value(MemorySegment udev_device, MemorySegment sysattr) { - var mh$ = udev_device_get_sysattr_value$MH(); + var mh$ = udev_device_get_sysattr_value.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_device, sysattr); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_device_get_sysattr_value", udev_device, sysattr); + } + return (MemorySegment)mh$.invokeExact(udev_device, sysattr); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_monitor_new_from_netlink$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$0,"udev_monitor_new_from_netlink"); + + private static class udev_monitor_new_from_netlink { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_monitor_new_from_netlink"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * struct udev_monitor* udev_monitor_new_from_netlink(struct udev* udev, char* name); + * Function descriptor for: + * {@snippet lang=c : + * struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) + * } + */ + public static FunctionDescriptor udev_monitor_new_from_netlink$descriptor() { + return udev_monitor_new_from_netlink.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) + * } + */ + public static MethodHandle udev_monitor_new_from_netlink$handle() { + return udev_monitor_new_from_netlink.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) + * } + */ + public static MemorySegment udev_monitor_new_from_netlink$address() { + return udev_monitor_new_from_netlink.ADDR; + } + + /** + * {@snippet lang=c : + * struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) * } */ public static MemorySegment udev_monitor_new_from_netlink(MemorySegment udev, MemorySegment name) { - var mh$ = udev_monitor_new_from_netlink$MH(); + var mh$ = udev_monitor_new_from_netlink.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev, name); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_monitor_new_from_netlink", udev, name); + } + return (MemorySegment)mh$.invokeExact(udev, name); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_monitor_enable_receiving$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$2,"udev_monitor_enable_receiving"); + + private static class udev_monitor_enable_receiving { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_INT, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_monitor_enable_receiving"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) + * } + */ + public static FunctionDescriptor udev_monitor_enable_receiving$descriptor() { + return udev_monitor_enable_receiving.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) + * } + */ + public static MethodHandle udev_monitor_enable_receiving$handle() { + return udev_monitor_enable_receiving.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) + * } + */ + public static MemorySegment udev_monitor_enable_receiving$address() { + return udev_monitor_enable_receiving.ADDR; } + /** - * {@snippet : - * int udev_monitor_enable_receiving(struct udev_monitor* udev_monitor); + * {@snippet lang=c : + * int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) * } */ public static int udev_monitor_enable_receiving(MemorySegment udev_monitor) { - var mh$ = udev_monitor_enable_receiving$MH(); + var mh$ = udev_monitor_enable_receiving.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("udev_monitor_enable_receiving", udev_monitor); + } return (int)mh$.invokeExact(udev_monitor); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_monitor_get_fd$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$3,"udev_monitor_get_fd"); + + private static class udev_monitor_get_fd { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_INT, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_monitor_get_fd"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int udev_monitor_get_fd(struct udev_monitor *udev_monitor) + * } + */ + public static FunctionDescriptor udev_monitor_get_fd$descriptor() { + return udev_monitor_get_fd.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int udev_monitor_get_fd(struct udev_monitor *udev_monitor) + * } + */ + public static MethodHandle udev_monitor_get_fd$handle() { + return udev_monitor_get_fd.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int udev_monitor_get_fd(struct udev_monitor *udev_monitor) + * } + */ + public static MemorySegment udev_monitor_get_fd$address() { + return udev_monitor_get_fd.ADDR; } + /** - * {@snippet : - * int udev_monitor_get_fd(struct udev_monitor* udev_monitor); + * {@snippet lang=c : + * int udev_monitor_get_fd(struct udev_monitor *udev_monitor) * } */ public static int udev_monitor_get_fd(MemorySegment udev_monitor) { - var mh$ = udev_monitor_get_fd$MH(); + var mh$ = udev_monitor_get_fd.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("udev_monitor_get_fd", udev_monitor); + } return (int)mh$.invokeExact(udev_monitor); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_monitor_receive_device$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$4,"udev_monitor_receive_device"); + + private static class udev_monitor_receive_device { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_monitor_receive_device"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) + * } + */ + public static FunctionDescriptor udev_monitor_receive_device$descriptor() { + return udev_monitor_receive_device.DESC; } + /** - * {@snippet : - * struct udev_device* udev_monitor_receive_device(struct udev_monitor* udev_monitor); + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) + * } + */ + public static MethodHandle udev_monitor_receive_device$handle() { + return udev_monitor_receive_device.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) + * } + */ + public static MemorySegment udev_monitor_receive_device$address() { + return udev_monitor_receive_device.ADDR; + } + + /** + * {@snippet lang=c : + * struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) * } */ public static MemorySegment udev_monitor_receive_device(MemorySegment udev_monitor) { - var mh$ = udev_monitor_receive_device$MH(); + var mh$ = udev_monitor_receive_device.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_monitor); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_monitor_receive_device", udev_monitor); + } + return (MemorySegment)mh$.invokeExact(udev_monitor); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_monitor_filter_add_match_subsystem_devtype$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$6,"udev_monitor_filter_add_match_subsystem_devtype"); + + private static class udev_monitor_filter_add_match_subsystem_devtype { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_INT, + udev.C_POINTER, + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_monitor_filter_add_match_subsystem_devtype"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) + * } + */ + public static FunctionDescriptor udev_monitor_filter_add_match_subsystem_devtype$descriptor() { + return udev_monitor_filter_add_match_subsystem_devtype.DESC; } + /** - * {@snippet : - * int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor* udev_monitor, char* subsystem, char* devtype); + * Downcall method handle for: + * {@snippet lang=c : + * int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) + * } + */ + public static MethodHandle udev_monitor_filter_add_match_subsystem_devtype$handle() { + return udev_monitor_filter_add_match_subsystem_devtype.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) + * } + */ + public static MemorySegment udev_monitor_filter_add_match_subsystem_devtype$address() { + return udev_monitor_filter_add_match_subsystem_devtype.ADDR; + } + + /** + * {@snippet lang=c : + * int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) * } */ public static int udev_monitor_filter_add_match_subsystem_devtype(MemorySegment udev_monitor, MemorySegment subsystem, MemorySegment devtype) { - var mh$ = udev_monitor_filter_add_match_subsystem_devtype$MH(); + var mh$ = udev_monitor_filter_add_match_subsystem_devtype.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("udev_monitor_filter_add_match_subsystem_devtype", udev_monitor, subsystem, devtype); + } return (int)mh$.invokeExact(udev_monitor, subsystem, devtype); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_enumerate_unref$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$0,"udev_enumerate_unref"); + + private static class udev_enumerate_unref { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_enumerate_unref"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * struct udev_enumerate* udev_enumerate_unref(struct udev_enumerate* udev_enumerate); + * Function descriptor for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) + * } + */ + public static FunctionDescriptor udev_enumerate_unref$descriptor() { + return udev_enumerate_unref.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) + * } + */ + public static MethodHandle udev_enumerate_unref$handle() { + return udev_enumerate_unref.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) + * } + */ + public static MemorySegment udev_enumerate_unref$address() { + return udev_enumerate_unref.ADDR; + } + + /** + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) * } */ public static MemorySegment udev_enumerate_unref(MemorySegment udev_enumerate) { - var mh$ = udev_enumerate_unref$MH(); + var mh$ = udev_enumerate_unref.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_enumerate); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_enumerate_unref", udev_enumerate); + } + return (MemorySegment)mh$.invokeExact(udev_enumerate); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_enumerate_new$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$1,"udev_enumerate_new"); + + private static class udev_enumerate_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_enumerate_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_new(struct udev *udev) + * } + */ + public static FunctionDescriptor udev_enumerate_new$descriptor() { + return udev_enumerate_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_new(struct udev *udev) + * } + */ + public static MethodHandle udev_enumerate_new$handle() { + return udev_enumerate_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_new(struct udev *udev) + * } + */ + public static MemorySegment udev_enumerate_new$address() { + return udev_enumerate_new.ADDR; } + /** - * {@snippet : - * struct udev_enumerate* udev_enumerate_new(struct udev* udev); + * {@snippet lang=c : + * struct udev_enumerate *udev_enumerate_new(struct udev *udev) * } */ public static MemorySegment udev_enumerate_new(MemorySegment udev) { - var mh$ = udev_enumerate_new$MH(); + var mh$ = udev_enumerate_new.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_enumerate_new", udev); + } + return (MemorySegment)mh$.invokeExact(udev); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_enumerate_add_match_subsystem$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$3,"udev_enumerate_add_match_subsystem"); + + private static class udev_enumerate_add_match_subsystem { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_INT, + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_enumerate_add_match_subsystem"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * int udev_enumerate_add_match_subsystem(struct udev_enumerate* udev_enumerate, char* subsystem); + * Function descriptor for: + * {@snippet lang=c : + * int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) + * } + */ + public static FunctionDescriptor udev_enumerate_add_match_subsystem$descriptor() { + return udev_enumerate_add_match_subsystem.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) + * } + */ + public static MethodHandle udev_enumerate_add_match_subsystem$handle() { + return udev_enumerate_add_match_subsystem.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) + * } + */ + public static MemorySegment udev_enumerate_add_match_subsystem$address() { + return udev_enumerate_add_match_subsystem.ADDR; + } + + /** + * {@snippet lang=c : + * int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) * } */ public static int udev_enumerate_add_match_subsystem(MemorySegment udev_enumerate, MemorySegment subsystem) { - var mh$ = udev_enumerate_add_match_subsystem$MH(); + var mh$ = udev_enumerate_add_match_subsystem.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("udev_enumerate_add_match_subsystem", udev_enumerate, subsystem); + } return (int)mh$.invokeExact(udev_enumerate, subsystem); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_enumerate_scan_devices$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$4,"udev_enumerate_scan_devices"); + + private static class udev_enumerate_scan_devices { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_INT, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_enumerate_scan_devices"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * int udev_enumerate_scan_devices(struct udev_enumerate* udev_enumerate); + * Function descriptor for: + * {@snippet lang=c : + * int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) + * } + */ + public static FunctionDescriptor udev_enumerate_scan_devices$descriptor() { + return udev_enumerate_scan_devices.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) + * } + */ + public static MethodHandle udev_enumerate_scan_devices$handle() { + return udev_enumerate_scan_devices.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) + * } + */ + public static MemorySegment udev_enumerate_scan_devices$address() { + return udev_enumerate_scan_devices.ADDR; + } + + /** + * {@snippet lang=c : + * int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) * } */ public static int udev_enumerate_scan_devices(MemorySegment udev_enumerate) { - var mh$ = udev_enumerate_scan_devices$MH(); + var mh$ = udev_enumerate_scan_devices.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("udev_enumerate_scan_devices", udev_enumerate); + } return (int)mh$.invokeExact(udev_enumerate); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle udev_enumerate_get_list_entry$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$5,"udev_enumerate_get_list_entry"); + + private static class udev_enumerate_get_list_entry { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + udev.C_POINTER, + udev.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("udev_enumerate_get_list_entry"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) + * } + */ + public static FunctionDescriptor udev_enumerate_get_list_entry$descriptor() { + return udev_enumerate_get_list_entry.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) + * } + */ + public static MethodHandle udev_enumerate_get_list_entry$handle() { + return udev_enumerate_get_list_entry.HANDLE; } + /** - * {@snippet : - * struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate* udev_enumerate); + * Address for: + * {@snippet lang=c : + * struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) + * } + */ + public static MemorySegment udev_enumerate_get_list_entry$address() { + return udev_enumerate_get_list_entry.ADDR; + } + + /** + * {@snippet lang=c : + * struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) * } */ public static MemorySegment udev_enumerate_get_list_entry(MemorySegment udev_enumerate) { - var mh$ = udev_enumerate_get_list_entry$MH(); + var mh$ = udev_enumerate_get_list_entry.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(udev_enumerate); + if (TRACE_DOWNCALLS) { + traceDowncall("udev_enumerate_get_list_entry", udev_enumerate); + } + return (MemorySegment)mh$.invokeExact(udev_enumerate); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/RuntimeHelper.java deleted file mode 100644 index f3cff469..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.unistd; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/constants$0.java deleted file mode 100644 index 90d07fa3..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/constants$0.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.unistd; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - JAVA_INT - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "close", - constants$0.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd$shared.java new file mode 100644 index 00000000..11064c54 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.unistd; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class unistd$shared { + + unistd$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd.java index 581e508e..e0f89fcf 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/unistd/unistd.java @@ -2,36 +2,86 @@ package net.codecrete.usb.linux.gen.unistd; -import java.lang.foreign.AddressLayout; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class unistd { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle close$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"close"); +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class unistd extends unistd$shared { + + unistd() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + + private static class close { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + unistd.C_INT, + unistd.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("close"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern int close(int __fd) + * } + */ + public static FunctionDescriptor close$descriptor() { + return close.DESC; } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern int close(int __fd) + * } + */ + public static MethodHandle close$handle() { + return close.HANDLE; + } + /** - * {@snippet : - * int close(int __fd); + * Address for: + * {@snippet lang=c : + * extern int close(int __fd) + * } + */ + public static MemorySegment close$address() { + return close.ADDR; + } + + /** + * {@snippet lang=c : + * extern int close(int __fd) * } */ public static int close(int __fd) { - var mh$ = close$MH(); + var mh$ = close.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("close", __fd); + } return (int)mh$.invokeExact(__fd); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/RuntimeHelper.java deleted file mode 100644 index 5e6d3cd8..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.linux.gen.usbdevice_fs; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$0.java deleted file mode 100644 index 24688f13..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$0.java +++ /dev/null @@ -1,31 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_BYTE.withName("bRequestType"), - JAVA_BYTE.withName("bRequest"), - JAVA_SHORT.withName("wValue"), - JAVA_SHORT.withName("wIndex"), - JAVA_SHORT.withName("wLength"), - JAVA_INT.withName("timeout"), - MemoryLayout.paddingLayout(4), - RuntimeHelper.POINTER.withName("data") - ).withName("usbdevfs_ctrltransfer"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("bRequestType")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("bRequest")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wValue")); - static final VarHandle const$4 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wIndex")); - static final VarHandle const$5 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wLength")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$1.java deleted file mode 100644 index 9666d212..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$1.java +++ /dev/null @@ -1,28 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final VarHandle const$0 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("timeout")); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("data")); - static final StructLayout const$2 = MemoryLayout.structLayout( - JAVA_INT.withName("ep"), - JAVA_INT.withName("len"), - JAVA_INT.withName("timeout"), - MemoryLayout.paddingLayout(4), - RuntimeHelper.POINTER.withName("data") - ).withName("usbdevfs_bulktransfer"); - static final VarHandle const$3 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("ep")); - static final VarHandle const$4 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("len")); - static final VarHandle const$5 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("timeout")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$2.java deleted file mode 100644 index 384a0622..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$2.java +++ /dev/null @@ -1,49 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final VarHandle const$0 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("data")); - static final StructLayout const$1 = MemoryLayout.structLayout( - JAVA_INT.withName("interface"), - JAVA_INT.withName("altsetting") - ).withName("usbdevfs_setinterface"); - static final VarHandle const$2 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("interface")); - static final VarHandle const$3 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("altsetting")); - static final StructLayout const$4 = MemoryLayout.structLayout( - JAVA_BYTE.withName("type"), - JAVA_BYTE.withName("endpoint"), - MemoryLayout.paddingLayout(2), - JAVA_INT.withName("status"), - JAVA_INT.withName("flags"), - MemoryLayout.paddingLayout(4), - RuntimeHelper.POINTER.withName("buffer"), - JAVA_INT.withName("buffer_length"), - JAVA_INT.withName("actual_length"), - JAVA_INT.withName("start_frame"), - MemoryLayout.unionLayout( - JAVA_INT.withName("number_of_packets"), - JAVA_INT.withName("stream_id") - ).withName("$anon$0"), - JAVA_INT.withName("error_count"), - JAVA_INT.withName("signr"), - RuntimeHelper.POINTER.withName("usercontext"), - MemoryLayout.sequenceLayout(0, MemoryLayout.structLayout( - JAVA_INT.withName("length"), - JAVA_INT.withName("actual_length"), - JAVA_INT.withName("status") - ).withName("usbdevfs_iso_packet_desc")).withName("iso_frame_desc") - ).withName("usbdevfs_urb"); - static final VarHandle const$5 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("type")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$3.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$3.java deleted file mode 100644 index 2f58300d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$3.java +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$3 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$3() {} - static final VarHandle const$0 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("endpoint")); - static final VarHandle const$1 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("status")); - static final VarHandle const$2 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("flags")); - static final VarHandle const$3 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("buffer")); - static final VarHandle const$4 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("buffer_length")); - static final VarHandle const$5 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("actual_length")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$4.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$4.java deleted file mode 100644 index dd410c61..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$4.java +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$4 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$4() {} - static final VarHandle const$0 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("start_frame")); - static final VarHandle const$1 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("number_of_packets")); - static final VarHandle const$2 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("stream_id")); - static final VarHandle const$3 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("error_count")); - static final VarHandle const$4 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("signr")); - static final VarHandle const$5 = constants$2.const$4.varHandle(MemoryLayout.PathElement.groupElement("usercontext")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$5.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$5.java deleted file mode 100644 index fedeaec6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$5.java +++ /dev/null @@ -1,31 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$5 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$5() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withName("ifno"), - JAVA_INT.withName("ioctl_code"), - RuntimeHelper.POINTER.withName("data") - ).withName("usbdevfs_ioctl"); - static final VarHandle const$1 = constants$5.const$0.varHandle(MemoryLayout.PathElement.groupElement("ifno")); - static final VarHandle const$2 = constants$5.const$0.varHandle(MemoryLayout.PathElement.groupElement("ioctl_code")); - static final VarHandle const$3 = constants$5.const$0.varHandle(MemoryLayout.PathElement.groupElement("data")); - static final StructLayout const$4 = MemoryLayout.structLayout( - JAVA_INT.withName("interface"), - JAVA_INT.withName("flags"), - MemoryLayout.sequenceLayout(256, JAVA_BYTE).withName("driver") - ).withName("usbdevfs_disconnect_claim"); - static final VarHandle const$5 = constants$5.const$4.varHandle(MemoryLayout.PathElement.groupElement("interface")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$6.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$6.java deleted file mode 100644 index 787c95d8..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/constants$6.java +++ /dev/null @@ -1,14 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.linux.gen.usbdevice_fs; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$6 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$6() {} - static final VarHandle const$0 = constants$5.const$4.varHandle(MemoryLayout.PathElement.groupElement("flags")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_bulktransfer.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_bulktransfer.java index 07aa5f5e..5e4eba47 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_bulktransfer.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_bulktransfer.java @@ -2,140 +2,265 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_bulktransfer { * unsigned int ep; * unsigned int len; * unsigned int timeout; - * void* data; - * }; + * void *data; + * } * } */ public class usbdevfs_bulktransfer { - public static MemoryLayout $LAYOUT() { - return constants$1.const$2; + usbdevfs_bulktransfer() { + // Should not be called directly } - public static VarHandle ep$VH() { - return constants$1.const$3; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_INT.withName("ep"), + usbdevice_fs.C_INT.withName("len"), + usbdevice_fs.C_INT.withName("timeout"), + MemoryLayout.paddingLayout(4), + usbdevice_fs.C_POINTER.withName("data") + ).withName("usbdevfs_bulktransfer"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final OfInt ep$LAYOUT = (OfInt)$LAYOUT.select(groupElement("ep")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int ep + * } + */ + public static final OfInt ep$layout() { + return ep$LAYOUT; + } + + private static final long ep$OFFSET = $LAYOUT.byteOffset(groupElement("ep")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int ep + * } + */ + public static final long ep$offset() { + return ep$OFFSET; + } + /** * Getter for field: - * {@snippet : - * unsigned int ep; + * {@snippet lang=c : + * unsigned int ep * } */ - public static int ep$get(MemorySegment seg) { - return (int)constants$1.const$3.get(seg); + public static int ep(MemorySegment struct) { + return struct.get(ep$LAYOUT, ep$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int ep; + * {@snippet lang=c : + * unsigned int ep * } */ - public static void ep$set(MemorySegment seg, int x) { - constants$1.const$3.set(seg, x); + public static void ep(MemorySegment struct, int fieldValue) { + struct.set(ep$LAYOUT, ep$OFFSET, fieldValue); } - public static int ep$get(MemorySegment seg, long index) { - return (int)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ep$set(MemorySegment seg, long index, int x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt len$LAYOUT = (OfInt)$LAYOUT.select(groupElement("len")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int len + * } + */ + public static final OfInt len$layout() { + return len$LAYOUT; } - public static VarHandle len$VH() { - return constants$1.const$4; + + private static final long len$OFFSET = $LAYOUT.byteOffset(groupElement("len")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int len + * } + */ + public static final long len$offset() { + return len$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int len; + * {@snippet lang=c : + * unsigned int len * } */ - public static int len$get(MemorySegment seg) { - return (int)constants$1.const$4.get(seg); + public static int len(MemorySegment struct) { + return struct.get(len$LAYOUT, len$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int len; + * {@snippet lang=c : + * unsigned int len * } */ - public static void len$set(MemorySegment seg, int x) { - constants$1.const$4.set(seg, x); + public static void len(MemorySegment struct, int fieldValue) { + struct.set(len$LAYOUT, len$OFFSET, fieldValue); } - public static int len$get(MemorySegment seg, long index) { - return (int)constants$1.const$4.get(seg.asSlice(index*sizeof())); - } - public static void len$set(MemorySegment seg, long index, int x) { - constants$1.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt timeout$LAYOUT = (OfInt)$LAYOUT.select(groupElement("timeout")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int timeout + * } + */ + public static final OfInt timeout$layout() { + return timeout$LAYOUT; } - public static VarHandle timeout$VH() { - return constants$1.const$5; + + private static final long timeout$OFFSET = $LAYOUT.byteOffset(groupElement("timeout")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int timeout + * } + */ + public static final long timeout$offset() { + return timeout$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int timeout; + * {@snippet lang=c : + * unsigned int timeout * } */ - public static int timeout$get(MemorySegment seg) { - return (int)constants$1.const$5.get(seg); + public static int timeout(MemorySegment struct) { + return struct.get(timeout$LAYOUT, timeout$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int timeout; + * {@snippet lang=c : + * unsigned int timeout * } */ - public static void timeout$set(MemorySegment seg, int x) { - constants$1.const$5.set(seg, x); - } - public static int timeout$get(MemorySegment seg, long index) { - return (int)constants$1.const$5.get(seg.asSlice(index*sizeof())); + public static void timeout(MemorySegment struct, int fieldValue) { + struct.set(timeout$LAYOUT, timeout$OFFSET, fieldValue); } - public static void timeout$set(MemorySegment seg, long index, int x) { - constants$1.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout data$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("data")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final AddressLayout data$layout() { + return data$LAYOUT; } - public static VarHandle data$VH() { - return constants$2.const$0; + + private static final long data$OFFSET = $LAYOUT.byteOffset(groupElement("data")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final long data$offset() { + return data$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static MemorySegment data$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$2.const$0.get(seg); + public static MemorySegment data(MemorySegment struct) { + return struct.get(data$LAYOUT, data$OFFSET); } + /** * Setter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static void data$set(MemorySegment seg, MemorySegment x) { - constants$2.const$0.set(seg, x); + public static void data(MemorySegment struct, MemorySegment fieldValue) { + struct.set(data$LAYOUT, data$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static MemorySegment data$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$2.const$0.get(seg.asSlice(index*sizeof())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static void data$set(MemorySegment seg, long index, MemorySegment x) { - constants$2.const$0.set(seg.asSlice(index*sizeof()), x); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ctrltransfer.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ctrltransfer.java index c32eba2f..c5071566 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ctrltransfer.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ctrltransfer.java @@ -2,13 +2,18 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_ctrltransfer { * __u8 bRequestType; * __u8 bRequest; @@ -16,210 +21,384 @@ * __u16 wIndex; * __u16 wLength; * __u32 timeout; - * void* data; - * }; + * void *data; + * } * } */ public class usbdevfs_ctrltransfer { - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; + usbdevfs_ctrltransfer() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_CHAR.withName("bRequestType"), + usbdevice_fs.C_CHAR.withName("bRequest"), + usbdevice_fs.C_SHORT.withName("wValue"), + usbdevice_fs.C_SHORT.withName("wIndex"), + usbdevice_fs.C_SHORT.withName("wLength"), + usbdevice_fs.C_INT.withName("timeout"), + MemoryLayout.paddingLayout(4), + usbdevice_fs.C_POINTER.withName("data") + ).withName("usbdevfs_ctrltransfer"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } - public static VarHandle bRequestType$VH() { - return constants$0.const$1; + + private static final OfByte bRequestType$LAYOUT = (OfByte)$LAYOUT.select(groupElement("bRequestType")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u8 bRequestType + * } + */ + public static final OfByte bRequestType$layout() { + return bRequestType$LAYOUT; + } + + private static final long bRequestType$OFFSET = $LAYOUT.byteOffset(groupElement("bRequestType")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u8 bRequestType + * } + */ + public static final long bRequestType$offset() { + return bRequestType$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u8 bRequestType; + * {@snippet lang=c : + * __u8 bRequestType * } */ - public static byte bRequestType$get(MemorySegment seg) { - return (byte)constants$0.const$1.get(seg); + public static byte bRequestType(MemorySegment struct) { + return struct.get(bRequestType$LAYOUT, bRequestType$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u8 bRequestType; + * {@snippet lang=c : + * __u8 bRequestType * } */ - public static void bRequestType$set(MemorySegment seg, byte x) { - constants$0.const$1.set(seg, x); + public static void bRequestType(MemorySegment struct, byte fieldValue) { + struct.set(bRequestType$LAYOUT, bRequestType$OFFSET, fieldValue); } - public static byte bRequestType$get(MemorySegment seg, long index) { - return (byte)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void bRequestType$set(MemorySegment seg, long index, byte x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte bRequest$LAYOUT = (OfByte)$LAYOUT.select(groupElement("bRequest")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u8 bRequest + * } + */ + public static final OfByte bRequest$layout() { + return bRequest$LAYOUT; } - public static VarHandle bRequest$VH() { - return constants$0.const$2; + + private static final long bRequest$OFFSET = $LAYOUT.byteOffset(groupElement("bRequest")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u8 bRequest + * } + */ + public static final long bRequest$offset() { + return bRequest$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u8 bRequest; + * {@snippet lang=c : + * __u8 bRequest * } */ - public static byte bRequest$get(MemorySegment seg) { - return (byte)constants$0.const$2.get(seg); + public static byte bRequest(MemorySegment struct) { + return struct.get(bRequest$LAYOUT, bRequest$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u8 bRequest; + * {@snippet lang=c : + * __u8 bRequest * } */ - public static void bRequest$set(MemorySegment seg, byte x) { - constants$0.const$2.set(seg, x); + public static void bRequest(MemorySegment struct, byte fieldValue) { + struct.set(bRequest$LAYOUT, bRequest$OFFSET, fieldValue); } - public static byte bRequest$get(MemorySegment seg, long index) { - return (byte)constants$0.const$2.get(seg.asSlice(index*sizeof())); - } - public static void bRequest$set(MemorySegment seg, long index, byte x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wValue$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wValue")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u16 wValue + * } + */ + public static final OfShort wValue$layout() { + return wValue$LAYOUT; } - public static VarHandle wValue$VH() { - return constants$0.const$3; + + private static final long wValue$OFFSET = $LAYOUT.byteOffset(groupElement("wValue")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u16 wValue + * } + */ + public static final long wValue$offset() { + return wValue$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u16 wValue; + * {@snippet lang=c : + * __u16 wValue * } */ - public static short wValue$get(MemorySegment seg) { - return (short)constants$0.const$3.get(seg); + public static short wValue(MemorySegment struct) { + return struct.get(wValue$LAYOUT, wValue$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u16 wValue; + * {@snippet lang=c : + * __u16 wValue * } */ - public static void wValue$set(MemorySegment seg, short x) { - constants$0.const$3.set(seg, x); + public static void wValue(MemorySegment struct, short fieldValue) { + struct.set(wValue$LAYOUT, wValue$OFFSET, fieldValue); } - public static short wValue$get(MemorySegment seg, long index) { - return (short)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void wValue$set(MemorySegment seg, long index, short x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wIndex$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wIndex")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u16 wIndex + * } + */ + public static final OfShort wIndex$layout() { + return wIndex$LAYOUT; } - public static VarHandle wIndex$VH() { - return constants$0.const$4; + + private static final long wIndex$OFFSET = $LAYOUT.byteOffset(groupElement("wIndex")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u16 wIndex + * } + */ + public static final long wIndex$offset() { + return wIndex$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u16 wIndex; + * {@snippet lang=c : + * __u16 wIndex * } */ - public static short wIndex$get(MemorySegment seg) { - return (short)constants$0.const$4.get(seg); + public static short wIndex(MemorySegment struct) { + return struct.get(wIndex$LAYOUT, wIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u16 wIndex; + * {@snippet lang=c : + * __u16 wIndex * } */ - public static void wIndex$set(MemorySegment seg, short x) { - constants$0.const$4.set(seg, x); + public static void wIndex(MemorySegment struct, short fieldValue) { + struct.set(wIndex$LAYOUT, wIndex$OFFSET, fieldValue); } - public static short wIndex$get(MemorySegment seg, long index) { - return (short)constants$0.const$4.get(seg.asSlice(index*sizeof())); - } - public static void wIndex$set(MemorySegment seg, long index, short x) { - constants$0.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wLength$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wLength")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u16 wLength + * } + */ + public static final OfShort wLength$layout() { + return wLength$LAYOUT; } - public static VarHandle wLength$VH() { - return constants$0.const$5; + + private static final long wLength$OFFSET = $LAYOUT.byteOffset(groupElement("wLength")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u16 wLength + * } + */ + public static final long wLength$offset() { + return wLength$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u16 wLength; + * {@snippet lang=c : + * __u16 wLength * } */ - public static short wLength$get(MemorySegment seg) { - return (short)constants$0.const$5.get(seg); + public static short wLength(MemorySegment struct) { + return struct.get(wLength$LAYOUT, wLength$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u16 wLength; + * {@snippet lang=c : + * __u16 wLength * } */ - public static void wLength$set(MemorySegment seg, short x) { - constants$0.const$5.set(seg, x); - } - public static short wLength$get(MemorySegment seg, long index) { - return (short)constants$0.const$5.get(seg.asSlice(index*sizeof())); + public static void wLength(MemorySegment struct, short fieldValue) { + struct.set(wLength$LAYOUT, wLength$OFFSET, fieldValue); } - public static void wLength$set(MemorySegment seg, long index, short x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt timeout$LAYOUT = (OfInt)$LAYOUT.select(groupElement("timeout")); + + /** + * Layout for field: + * {@snippet lang=c : + * __u32 timeout + * } + */ + public static final OfInt timeout$layout() { + return timeout$LAYOUT; } - public static VarHandle timeout$VH() { - return constants$1.const$0; + + private static final long timeout$OFFSET = $LAYOUT.byteOffset(groupElement("timeout")); + + /** + * Offset for field: + * {@snippet lang=c : + * __u32 timeout + * } + */ + public static final long timeout$offset() { + return timeout$OFFSET; } + /** * Getter for field: - * {@snippet : - * __u32 timeout; + * {@snippet lang=c : + * __u32 timeout * } */ - public static int timeout$get(MemorySegment seg) { - return (int)constants$1.const$0.get(seg); + public static int timeout(MemorySegment struct) { + return struct.get(timeout$LAYOUT, timeout$OFFSET); } + /** * Setter for field: - * {@snippet : - * __u32 timeout; + * {@snippet lang=c : + * __u32 timeout * } */ - public static void timeout$set(MemorySegment seg, int x) { - constants$1.const$0.set(seg, x); - } - public static int timeout$get(MemorySegment seg, long index) { - return (int)constants$1.const$0.get(seg.asSlice(index*sizeof())); + public static void timeout(MemorySegment struct, int fieldValue) { + struct.set(timeout$LAYOUT, timeout$OFFSET, fieldValue); } - public static void timeout$set(MemorySegment seg, long index, int x) { - constants$1.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout data$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("data")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final AddressLayout data$layout() { + return data$LAYOUT; } - public static VarHandle data$VH() { - return constants$1.const$1; + + private static final long data$OFFSET = $LAYOUT.byteOffset(groupElement("data")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final long data$offset() { + return data$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static MemorySegment data$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$1.get(seg); + public static MemorySegment data(MemorySegment struct) { + return struct.get(data$LAYOUT, data$OFFSET); } + /** * Setter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static void data$set(MemorySegment seg, MemorySegment x) { - constants$1.const$1.set(seg, x); + public static void data(MemorySegment struct, MemorySegment fieldValue) { + struct.set(data$LAYOUT, data$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static MemorySegment data$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$1.get(seg.asSlice(index*sizeof())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static void data$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_disconnect_claim.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_disconnect_claim.java index e238d86e..a41ba1db 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_disconnect_claim.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_disconnect_claim.java @@ -2,88 +2,251 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_disconnect_claim { * unsigned int interface; * unsigned int flags; * char driver[256]; - * }; + * } * } */ public class usbdevfs_disconnect_claim { - public static MemoryLayout $LAYOUT() { - return constants$5.const$4; + usbdevfs_disconnect_claim() { + // Should not be called directly } - public static VarHandle interface_$VH() { - return constants$5.const$5; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_INT.withName("interface"), + usbdevice_fs.C_INT.withName("flags"), + MemoryLayout.sequenceLayout(256, usbdevice_fs.C_CHAR).withName("driver") + ).withName("usbdevfs_disconnect_claim"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final OfInt interface_$LAYOUT = (OfInt)$LAYOUT.select(groupElement("interface")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int interface + * } + */ + public static final OfInt interface_$layout() { + return interface_$LAYOUT; + } + + private static final long interface_$OFFSET = $LAYOUT.byteOffset(groupElement("interface")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int interface + * } + */ + public static final long interface_$offset() { + return interface_$OFFSET; + } + /** * Getter for field: - * {@snippet : - * unsigned int interface; + * {@snippet lang=c : + * unsigned int interface * } */ - public static int interface_$get(MemorySegment seg) { - return (int)constants$5.const$5.get(seg); + public static int interface_(MemorySegment struct) { + return struct.get(interface_$LAYOUT, interface_$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int interface; + * {@snippet lang=c : + * unsigned int interface + * } + */ + public static void interface_(MemorySegment struct, int fieldValue) { + struct.set(interface_$LAYOUT, interface_$OFFSET, fieldValue); + } + + private static final OfInt flags$LAYOUT = (OfInt)$LAYOUT.select(groupElement("flags")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int flags * } */ - public static void interface_$set(MemorySegment seg, int x) { - constants$5.const$5.set(seg, x); + public static final OfInt flags$layout() { + return flags$LAYOUT; } - public static int interface_$get(MemorySegment seg, long index) { - return (int)constants$5.const$5.get(seg.asSlice(index*sizeof())); + + private static final long flags$OFFSET = $LAYOUT.byteOffset(groupElement("flags")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int flags + * } + */ + public static final long flags$offset() { + return flags$OFFSET; } - public static void interface_$set(MemorySegment seg, long index, int x) { - constants$5.const$5.set(seg.asSlice(index*sizeof()), x); + + /** + * Getter for field: + * {@snippet lang=c : + * unsigned int flags + * } + */ + public static int flags(MemorySegment struct) { + return struct.get(flags$LAYOUT, flags$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * unsigned int flags + * } + */ + public static void flags(MemorySegment struct, int fieldValue) { + struct.set(flags$LAYOUT, flags$OFFSET, fieldValue); + } + + private static final SequenceLayout driver$LAYOUT = (SequenceLayout)$LAYOUT.select(groupElement("driver")); + + /** + * Layout for field: + * {@snippet lang=c : + * char driver[256] + * } + */ + public static final SequenceLayout driver$layout() { + return driver$LAYOUT; } - public static VarHandle flags$VH() { - return constants$6.const$0; + + private static final long driver$OFFSET = $LAYOUT.byteOffset(groupElement("driver")); + + /** + * Offset for field: + * {@snippet lang=c : + * char driver[256] + * } + */ + public static final long driver$offset() { + return driver$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int flags; + * {@snippet lang=c : + * char driver[256] * } */ - public static int flags$get(MemorySegment seg) { - return (int)constants$6.const$0.get(seg); + public static MemorySegment driver(MemorySegment struct) { + return struct.asSlice(driver$OFFSET, driver$LAYOUT.byteSize()); } + /** * Setter for field: - * {@snippet : - * unsigned int flags; + * {@snippet lang=c : + * char driver[256] + * } + */ + public static void driver(MemorySegment struct, MemorySegment fieldValue) { + MemorySegment.copy(fieldValue, 0L, struct, driver$OFFSET, driver$LAYOUT.byteSize()); + } + + private static long[] driver$DIMS = { 256 }; + + /** + * Dimensions for array field: + * {@snippet lang=c : + * char driver[256] + * } + */ + public static long[] driver$dimensions() { + return driver$DIMS; + } + private static final VarHandle driver$ELEM_HANDLE = driver$LAYOUT.varHandle(sequenceElement()); + + /** + * Indexed getter for field: + * {@snippet lang=c : + * char driver[256] + * } + */ + public static byte driver(MemorySegment struct, long index0) { + return (byte)driver$ELEM_HANDLE.get(struct, 0L, index0); + } + + /** + * Indexed setter for field: + * {@snippet lang=c : + * char driver[256] * } */ - public static void flags$set(MemorySegment seg, int x) { - constants$6.const$0.set(seg, x); + public static void driver(MemorySegment struct, long index0, byte fieldValue) { + driver$ELEM_HANDLE.set(struct, 0L, index0, fieldValue); } - public static int flags$get(MemorySegment seg, long index) { - return (int)constants$6.const$0.get(seg.asSlice(index*sizeof())); + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static void flags$set(MemorySegment seg, long index, int x) { - constants$6.const$0.set(seg.asSlice(index*sizeof()), x); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static MemorySegment driver$slice(MemorySegment seg) { - return seg.asSlice(8, 256); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ioctl.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ioctl.java index 8135f579..8d4b6143 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ioctl.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_ioctl.java @@ -2,112 +2,218 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_ioctl { * int ifno; * int ioctl_code; - * void* data; - * }; + * void *data; + * } * } */ public class usbdevfs_ioctl { - public static MemoryLayout $LAYOUT() { - return constants$5.const$0; + usbdevfs_ioctl() { + // Should not be called directly } - public static VarHandle ifno$VH() { - return constants$5.const$1; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_INT.withName("ifno"), + usbdevice_fs.C_INT.withName("ioctl_code"), + usbdevice_fs.C_POINTER.withName("data") + ).withName("usbdevfs_ioctl"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; + } + + private static final OfInt ifno$LAYOUT = (OfInt)$LAYOUT.select(groupElement("ifno")); + + /** + * Layout for field: + * {@snippet lang=c : + * int ifno + * } + */ + public static final OfInt ifno$layout() { + return ifno$LAYOUT; + } + + private static final long ifno$OFFSET = $LAYOUT.byteOffset(groupElement("ifno")); + + /** + * Offset for field: + * {@snippet lang=c : + * int ifno + * } + */ + public static final long ifno$offset() { + return ifno$OFFSET; } + /** * Getter for field: - * {@snippet : - * int ifno; + * {@snippet lang=c : + * int ifno * } */ - public static int ifno$get(MemorySegment seg) { - return (int)constants$5.const$1.get(seg); + public static int ifno(MemorySegment struct) { + return struct.get(ifno$LAYOUT, ifno$OFFSET); } + /** * Setter for field: - * {@snippet : - * int ifno; + * {@snippet lang=c : + * int ifno * } */ - public static void ifno$set(MemorySegment seg, int x) { - constants$5.const$1.set(seg, x); - } - public static int ifno$get(MemorySegment seg, long index) { - return (int)constants$5.const$1.get(seg.asSlice(index*sizeof())); + public static void ifno(MemorySegment struct, int fieldValue) { + struct.set(ifno$LAYOUT, ifno$OFFSET, fieldValue); } - public static void ifno$set(MemorySegment seg, long index, int x) { - constants$5.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt ioctl_code$LAYOUT = (OfInt)$LAYOUT.select(groupElement("ioctl_code")); + + /** + * Layout for field: + * {@snippet lang=c : + * int ioctl_code + * } + */ + public static final OfInt ioctl_code$layout() { + return ioctl_code$LAYOUT; } - public static VarHandle ioctl_code$VH() { - return constants$5.const$2; + + private static final long ioctl_code$OFFSET = $LAYOUT.byteOffset(groupElement("ioctl_code")); + + /** + * Offset for field: + * {@snippet lang=c : + * int ioctl_code + * } + */ + public static final long ioctl_code$offset() { + return ioctl_code$OFFSET; } + /** * Getter for field: - * {@snippet : - * int ioctl_code; + * {@snippet lang=c : + * int ioctl_code * } */ - public static int ioctl_code$get(MemorySegment seg) { - return (int)constants$5.const$2.get(seg); + public static int ioctl_code(MemorySegment struct) { + return struct.get(ioctl_code$LAYOUT, ioctl_code$OFFSET); } + /** * Setter for field: - * {@snippet : - * int ioctl_code; + * {@snippet lang=c : + * int ioctl_code * } */ - public static void ioctl_code$set(MemorySegment seg, int x) { - constants$5.const$2.set(seg, x); + public static void ioctl_code(MemorySegment struct, int fieldValue) { + struct.set(ioctl_code$LAYOUT, ioctl_code$OFFSET, fieldValue); } - public static int ioctl_code$get(MemorySegment seg, long index) { - return (int)constants$5.const$2.get(seg.asSlice(index*sizeof())); - } - public static void ioctl_code$set(MemorySegment seg, long index, int x) { - constants$5.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout data$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("data")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final AddressLayout data$layout() { + return data$LAYOUT; } - public static VarHandle data$VH() { - return constants$5.const$3; + + private static final long data$OFFSET = $LAYOUT.byteOffset(groupElement("data")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *data + * } + */ + public static final long data$offset() { + return data$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static MemorySegment data$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$5.const$3.get(seg); + public static MemorySegment data(MemorySegment struct) { + return struct.get(data$LAYOUT, data$OFFSET); } + /** * Setter for field: - * {@snippet : - * void* data; + * {@snippet lang=c : + * void *data * } */ - public static void data$set(MemorySegment seg, MemorySegment x) { - constants$5.const$3.set(seg, x); + public static void data(MemorySegment struct, MemorySegment fieldValue) { + struct.set(data$LAYOUT, data$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static MemorySegment data$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$5.const$3.get(seg.asSlice(index*sizeof())); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static void data$set(MemorySegment seg, long index, MemorySegment x) { - constants$5.const$3.set(seg.asSlice(index*sizeof()), x); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_iso_packet_desc.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_iso_packet_desc.java new file mode 100644 index 00000000..c269241e --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_iso_packet_desc.java @@ -0,0 +1,219 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.usbdevice_fs; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +/** + * {@snippet lang=c : + * struct usbdevfs_iso_packet_desc { + * unsigned int length; + * unsigned int actual_length; + * unsigned int status; + * } + * } + */ +public class usbdevfs_iso_packet_desc { + + usbdevfs_iso_packet_desc() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_INT.withName("length"), + usbdevice_fs.C_INT.withName("actual_length"), + usbdevice_fs.C_INT.withName("status") + ).withName("usbdevfs_iso_packet_desc"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; + } + + private static final OfInt length$LAYOUT = (OfInt)$LAYOUT.select(groupElement("length")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int length + * } + */ + public static final OfInt length$layout() { + return length$LAYOUT; + } + + private static final long length$OFFSET = $LAYOUT.byteOffset(groupElement("length")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int length + * } + */ + public static final long length$offset() { + return length$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * unsigned int length + * } + */ + public static int length(MemorySegment struct) { + return struct.get(length$LAYOUT, length$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * unsigned int length + * } + */ + public static void length(MemorySegment struct, int fieldValue) { + struct.set(length$LAYOUT, length$OFFSET, fieldValue); + } + + private static final OfInt actual_length$LAYOUT = (OfInt)$LAYOUT.select(groupElement("actual_length")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int actual_length + * } + */ + public static final OfInt actual_length$layout() { + return actual_length$LAYOUT; + } + + private static final long actual_length$OFFSET = $LAYOUT.byteOffset(groupElement("actual_length")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int actual_length + * } + */ + public static final long actual_length$offset() { + return actual_length$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * unsigned int actual_length + * } + */ + public static int actual_length(MemorySegment struct) { + return struct.get(actual_length$LAYOUT, actual_length$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * unsigned int actual_length + * } + */ + public static void actual_length(MemorySegment struct, int fieldValue) { + struct.set(actual_length$LAYOUT, actual_length$OFFSET, fieldValue); + } + + private static final OfInt status$LAYOUT = (OfInt)$LAYOUT.select(groupElement("status")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int status + * } + */ + public static final OfInt status$layout() { + return status$LAYOUT; + } + + private static final long status$OFFSET = $LAYOUT.byteOffset(groupElement("status")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int status + * } + */ + public static final long status$offset() { + return status$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * unsigned int status + * } + */ + public static int status(MemorySegment struct) { + return struct.get(status$LAYOUT, status$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * unsigned int status + * } + */ + public static void status(MemorySegment struct, int fieldValue) { + struct.set(status$LAYOUT, status$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); + } + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_setinterface.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_setinterface.java index b9989942..fdae516e 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_setinterface.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_setinterface.java @@ -2,84 +2,172 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_setinterface { * unsigned int interface; * unsigned int altsetting; - * }; + * } * } */ public class usbdevfs_setinterface { - public static MemoryLayout $LAYOUT() { - return constants$2.const$1; + usbdevfs_setinterface() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_INT.withName("interface"), + usbdevice_fs.C_INT.withName("altsetting") + ).withName("usbdevfs_setinterface"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; + } + + private static final OfInt interface_$LAYOUT = (OfInt)$LAYOUT.select(groupElement("interface")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int interface + * } + */ + public static final OfInt interface_$layout() { + return interface_$LAYOUT; } - public static VarHandle interface_$VH() { - return constants$2.const$2; + + private static final long interface_$OFFSET = $LAYOUT.byteOffset(groupElement("interface")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int interface + * } + */ + public static final long interface_$offset() { + return interface_$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int interface; + * {@snippet lang=c : + * unsigned int interface * } */ - public static int interface_$get(MemorySegment seg) { - return (int)constants$2.const$2.get(seg); + public static int interface_(MemorySegment struct) { + return struct.get(interface_$LAYOUT, interface_$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int interface; + * {@snippet lang=c : + * unsigned int interface * } */ - public static void interface_$set(MemorySegment seg, int x) { - constants$2.const$2.set(seg, x); + public static void interface_(MemorySegment struct, int fieldValue) { + struct.set(interface_$LAYOUT, interface_$OFFSET, fieldValue); } - public static int interface_$get(MemorySegment seg, long index) { - return (int)constants$2.const$2.get(seg.asSlice(index*sizeof())); - } - public static void interface_$set(MemorySegment seg, long index, int x) { - constants$2.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt altsetting$LAYOUT = (OfInt)$LAYOUT.select(groupElement("altsetting")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int altsetting + * } + */ + public static final OfInt altsetting$layout() { + return altsetting$LAYOUT; } - public static VarHandle altsetting$VH() { - return constants$2.const$3; + + private static final long altsetting$OFFSET = $LAYOUT.byteOffset(groupElement("altsetting")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int altsetting + * } + */ + public static final long altsetting$offset() { + return altsetting$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int altsetting; + * {@snippet lang=c : + * unsigned int altsetting * } */ - public static int altsetting$get(MemorySegment seg) { - return (int)constants$2.const$3.get(seg); + public static int altsetting(MemorySegment struct) { + return struct.get(altsetting$LAYOUT, altsetting$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int altsetting; + * {@snippet lang=c : + * unsigned int altsetting * } */ - public static void altsetting$set(MemorySegment seg, int x) { - constants$2.const$3.set(seg, x); + public static void altsetting(MemorySegment struct, int fieldValue) { + struct.set(altsetting$LAYOUT, altsetting$OFFSET, fieldValue); } - public static int altsetting$get(MemorySegment seg, long index) { - return (int)constants$2.const$3.get(seg.asSlice(index*sizeof())); + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static void altsetting$set(MemorySegment seg, long index, int x) { - constants$2.const$3.set(seg.asSlice(index*sizeof()), x); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_urb.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_urb.java index ab7fd8e6..556be6c4 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_urb.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevfs_urb.java @@ -2,19 +2,24 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct usbdevfs_urb { * unsigned char type; * unsigned char endpoint; * int status; * unsigned int flags; - * void* buffer; + * void *buffer; * int buffer_length; * int actual_length; * int start_frame; @@ -24,373 +29,612 @@ * }; * int error_count; * unsigned int signr; - * void* usercontext; - * struct usbdevfs_iso_packet_desc iso_frame_desc[0]; - * }; + * void *usercontext; + * struct usbdevfs_iso_packet_desc iso_frame_desc[]; + * } * } */ public class usbdevfs_urb { - public static MemoryLayout $LAYOUT() { - return constants$2.const$4; + usbdevfs_urb() { + // Should not be called directly } - public static VarHandle type$VH() { - return constants$2.const$5; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + usbdevice_fs.C_CHAR.withName("type"), + usbdevice_fs.C_CHAR.withName("endpoint"), + MemoryLayout.paddingLayout(2), + usbdevice_fs.C_INT.withName("status"), + usbdevice_fs.C_INT.withName("flags"), + MemoryLayout.paddingLayout(4), + usbdevice_fs.C_POINTER.withName("buffer"), + usbdevice_fs.C_INT.withName("buffer_length"), + usbdevice_fs.C_INT.withName("actual_length"), + usbdevice_fs.C_INT.withName("start_frame"), + MemoryLayout.paddingLayout(4), + usbdevice_fs.C_INT.withName("error_count"), + usbdevice_fs.C_INT.withName("signr"), + usbdevice_fs.C_POINTER.withName("usercontext"), + MemoryLayout.sequenceLayout(0, usbdevfs_iso_packet_desc.layout()).withName("iso_frame_desc") + ).withName("usbdevfs_urb"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final OfByte type$LAYOUT = (OfByte)$LAYOUT.select(groupElement("type")); + /** - * Getter for field: - * {@snippet : - * unsigned char type; + * Layout for field: + * {@snippet lang=c : + * unsigned char type * } */ - public static byte type$get(MemorySegment seg) { - return (byte)constants$2.const$5.get(seg); + public static final OfByte type$layout() { + return type$LAYOUT; } + + private static final long type$OFFSET = $LAYOUT.byteOffset(groupElement("type")); + /** - * Setter for field: - * {@snippet : - * unsigned char type; + * Offset for field: + * {@snippet lang=c : + * unsigned char type * } */ - public static void type$set(MemorySegment seg, byte x) { - constants$2.const$5.set(seg, x); - } - public static byte type$get(MemorySegment seg, long index) { - return (byte)constants$2.const$5.get(seg.asSlice(index*sizeof())); - } - public static void type$set(MemorySegment seg, long index, byte x) { - constants$2.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle endpoint$VH() { - return constants$3.const$0; + public static final long type$offset() { + return type$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned char endpoint; + * {@snippet lang=c : + * unsigned char type * } */ - public static byte endpoint$get(MemorySegment seg) { - return (byte)constants$3.const$0.get(seg); + public static byte type(MemorySegment struct) { + return struct.get(type$LAYOUT, type$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned char endpoint; + * {@snippet lang=c : + * unsigned char type * } */ - public static void endpoint$set(MemorySegment seg, byte x) { - constants$3.const$0.set(seg, x); + public static void type(MemorySegment struct, byte fieldValue) { + struct.set(type$LAYOUT, type$OFFSET, fieldValue); } - public static byte endpoint$get(MemorySegment seg, long index) { - return (byte)constants$3.const$0.get(seg.asSlice(index*sizeof())); - } - public static void endpoint$set(MemorySegment seg, long index, byte x) { - constants$3.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte endpoint$LAYOUT = (OfByte)$LAYOUT.select(groupElement("endpoint")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned char endpoint + * } + */ + public static final OfByte endpoint$layout() { + return endpoint$LAYOUT; } - public static VarHandle status$VH() { - return constants$3.const$1; + + private static final long endpoint$OFFSET = $LAYOUT.byteOffset(groupElement("endpoint")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned char endpoint + * } + */ + public static final long endpoint$offset() { + return endpoint$OFFSET; } + /** * Getter for field: - * {@snippet : - * int status; + * {@snippet lang=c : + * unsigned char endpoint * } */ - public static int status$get(MemorySegment seg) { - return (int)constants$3.const$1.get(seg); + public static byte endpoint(MemorySegment struct) { + return struct.get(endpoint$LAYOUT, endpoint$OFFSET); } + /** * Setter for field: - * {@snippet : - * int status; + * {@snippet lang=c : + * unsigned char endpoint * } */ - public static void status$set(MemorySegment seg, int x) { - constants$3.const$1.set(seg, x); - } - public static int status$get(MemorySegment seg, long index) { - return (int)constants$3.const$1.get(seg.asSlice(index*sizeof())); + public static void endpoint(MemorySegment struct, byte fieldValue) { + struct.set(endpoint$LAYOUT, endpoint$OFFSET, fieldValue); } - public static void status$set(MemorySegment seg, long index, int x) { - constants$3.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt status$LAYOUT = (OfInt)$LAYOUT.select(groupElement("status")); + + /** + * Layout for field: + * {@snippet lang=c : + * int status + * } + */ + public static final OfInt status$layout() { + return status$LAYOUT; } - public static VarHandle flags$VH() { - return constants$3.const$2; + + private static final long status$OFFSET = $LAYOUT.byteOffset(groupElement("status")); + + /** + * Offset for field: + * {@snippet lang=c : + * int status + * } + */ + public static final long status$offset() { + return status$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int flags; + * {@snippet lang=c : + * int status * } */ - public static int flags$get(MemorySegment seg) { - return (int)constants$3.const$2.get(seg); + public static int status(MemorySegment struct) { + return struct.get(status$LAYOUT, status$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int flags; + * {@snippet lang=c : + * int status * } */ - public static void flags$set(MemorySegment seg, int x) { - constants$3.const$2.set(seg, x); + public static void status(MemorySegment struct, int fieldValue) { + struct.set(status$LAYOUT, status$OFFSET, fieldValue); } - public static int flags$get(MemorySegment seg, long index) { - return (int)constants$3.const$2.get(seg.asSlice(index*sizeof())); - } - public static void flags$set(MemorySegment seg, long index, int x) { - constants$3.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt flags$LAYOUT = (OfInt)$LAYOUT.select(groupElement("flags")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int flags + * } + */ + public static final OfInt flags$layout() { + return flags$LAYOUT; } - public static VarHandle buffer$VH() { - return constants$3.const$3; + + private static final long flags$OFFSET = $LAYOUT.byteOffset(groupElement("flags")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int flags + * } + */ + public static final long flags$offset() { + return flags$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* buffer; + * {@snippet lang=c : + * unsigned int flags * } */ - public static MemorySegment buffer$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$3.const$3.get(seg); + public static int flags(MemorySegment struct) { + return struct.get(flags$LAYOUT, flags$OFFSET); } + /** * Setter for field: - * {@snippet : - * void* buffer; + * {@snippet lang=c : + * unsigned int flags * } */ - public static void buffer$set(MemorySegment seg, MemorySegment x) { - constants$3.const$3.set(seg, x); - } - public static MemorySegment buffer$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$3.const$3.get(seg.asSlice(index*sizeof())); + public static void flags(MemorySegment struct, int fieldValue) { + struct.set(flags$LAYOUT, flags$OFFSET, fieldValue); } - public static void buffer$set(MemorySegment seg, long index, MemorySegment x) { - constants$3.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout buffer$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("buffer")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *buffer + * } + */ + public static final AddressLayout buffer$layout() { + return buffer$LAYOUT; } - public static VarHandle buffer_length$VH() { - return constants$3.const$4; + + private static final long buffer$OFFSET = $LAYOUT.byteOffset(groupElement("buffer")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *buffer + * } + */ + public static final long buffer$offset() { + return buffer$OFFSET; } + /** * Getter for field: - * {@snippet : - * int buffer_length; + * {@snippet lang=c : + * void *buffer * } */ - public static int buffer_length$get(MemorySegment seg) { - return (int)constants$3.const$4.get(seg); + public static MemorySegment buffer(MemorySegment struct) { + return struct.get(buffer$LAYOUT, buffer$OFFSET); } + /** * Setter for field: - * {@snippet : - * int buffer_length; + * {@snippet lang=c : + * void *buffer * } */ - public static void buffer_length$set(MemorySegment seg, int x) { - constants$3.const$4.set(seg, x); - } - public static int buffer_length$get(MemorySegment seg, long index) { - return (int)constants$3.const$4.get(seg.asSlice(index*sizeof())); + public static void buffer(MemorySegment struct, MemorySegment fieldValue) { + struct.set(buffer$LAYOUT, buffer$OFFSET, fieldValue); } - public static void buffer_length$set(MemorySegment seg, long index, int x) { - constants$3.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt buffer_length$LAYOUT = (OfInt)$LAYOUT.select(groupElement("buffer_length")); + + /** + * Layout for field: + * {@snippet lang=c : + * int buffer_length + * } + */ + public static final OfInt buffer_length$layout() { + return buffer_length$LAYOUT; } - public static VarHandle actual_length$VH() { - return constants$3.const$5; + + private static final long buffer_length$OFFSET = $LAYOUT.byteOffset(groupElement("buffer_length")); + + /** + * Offset for field: + * {@snippet lang=c : + * int buffer_length + * } + */ + public static final long buffer_length$offset() { + return buffer_length$OFFSET; } + /** * Getter for field: - * {@snippet : - * int actual_length; + * {@snippet lang=c : + * int buffer_length * } */ - public static int actual_length$get(MemorySegment seg) { - return (int)constants$3.const$5.get(seg); + public static int buffer_length(MemorySegment struct) { + return struct.get(buffer_length$LAYOUT, buffer_length$OFFSET); } + /** * Setter for field: - * {@snippet : - * int actual_length; + * {@snippet lang=c : + * int buffer_length * } */ - public static void actual_length$set(MemorySegment seg, int x) { - constants$3.const$5.set(seg, x); + public static void buffer_length(MemorySegment struct, int fieldValue) { + struct.set(buffer_length$LAYOUT, buffer_length$OFFSET, fieldValue); } - public static int actual_length$get(MemorySegment seg, long index) { - return (int)constants$3.const$5.get(seg.asSlice(index*sizeof())); - } - public static void actual_length$set(MemorySegment seg, long index, int x) { - constants$3.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt actual_length$LAYOUT = (OfInt)$LAYOUT.select(groupElement("actual_length")); + + /** + * Layout for field: + * {@snippet lang=c : + * int actual_length + * } + */ + public static final OfInt actual_length$layout() { + return actual_length$LAYOUT; } - public static VarHandle start_frame$VH() { - return constants$4.const$0; + + private static final long actual_length$OFFSET = $LAYOUT.byteOffset(groupElement("actual_length")); + + /** + * Offset for field: + * {@snippet lang=c : + * int actual_length + * } + */ + public static final long actual_length$offset() { + return actual_length$OFFSET; } + /** * Getter for field: - * {@snippet : - * int start_frame; + * {@snippet lang=c : + * int actual_length * } */ - public static int start_frame$get(MemorySegment seg) { - return (int)constants$4.const$0.get(seg); + public static int actual_length(MemorySegment struct) { + return struct.get(actual_length$LAYOUT, actual_length$OFFSET); } + /** * Setter for field: - * {@snippet : - * int start_frame; + * {@snippet lang=c : + * int actual_length * } */ - public static void start_frame$set(MemorySegment seg, int x) { - constants$4.const$0.set(seg, x); - } - public static int start_frame$get(MemorySegment seg, long index) { - return (int)constants$4.const$0.get(seg.asSlice(index*sizeof())); + public static void actual_length(MemorySegment struct, int fieldValue) { + struct.set(actual_length$LAYOUT, actual_length$OFFSET, fieldValue); } - public static void start_frame$set(MemorySegment seg, long index, int x) { - constants$4.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt start_frame$LAYOUT = (OfInt)$LAYOUT.select(groupElement("start_frame")); + + /** + * Layout for field: + * {@snippet lang=c : + * int start_frame + * } + */ + public static final OfInt start_frame$layout() { + return start_frame$LAYOUT; } - public static VarHandle number_of_packets$VH() { - return constants$4.const$1; + + private static final long start_frame$OFFSET = $LAYOUT.byteOffset(groupElement("start_frame")); + + /** + * Offset for field: + * {@snippet lang=c : + * int start_frame + * } + */ + public static final long start_frame$offset() { + return start_frame$OFFSET; } + /** * Getter for field: - * {@snippet : - * int number_of_packets; + * {@snippet lang=c : + * int start_frame * } */ - public static int number_of_packets$get(MemorySegment seg) { - return (int)constants$4.const$1.get(seg); + public static int start_frame(MemorySegment struct) { + return struct.get(start_frame$LAYOUT, start_frame$OFFSET); } + /** * Setter for field: - * {@snippet : - * int number_of_packets; + * {@snippet lang=c : + * int start_frame * } */ - public static void number_of_packets$set(MemorySegment seg, int x) { - constants$4.const$1.set(seg, x); + public static void start_frame(MemorySegment struct, int fieldValue) { + struct.set(start_frame$LAYOUT, start_frame$OFFSET, fieldValue); } - public static int number_of_packets$get(MemorySegment seg, long index) { - return (int)constants$4.const$1.get(seg.asSlice(index*sizeof())); - } - public static void number_of_packets$set(MemorySegment seg, long index, int x) { - constants$4.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt error_count$LAYOUT = (OfInt)$LAYOUT.select(groupElement("error_count")); + + /** + * Layout for field: + * {@snippet lang=c : + * int error_count + * } + */ + public static final OfInt error_count$layout() { + return error_count$LAYOUT; } - public static VarHandle stream_id$VH() { - return constants$4.const$2; + + private static final long error_count$OFFSET = $LAYOUT.byteOffset(groupElement("error_count")); + + /** + * Offset for field: + * {@snippet lang=c : + * int error_count + * } + */ + public static final long error_count$offset() { + return error_count$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int stream_id; + * {@snippet lang=c : + * int error_count * } */ - public static int stream_id$get(MemorySegment seg) { - return (int)constants$4.const$2.get(seg); + public static int error_count(MemorySegment struct) { + return struct.get(error_count$LAYOUT, error_count$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int stream_id; + * {@snippet lang=c : + * int error_count * } */ - public static void stream_id$set(MemorySegment seg, int x) { - constants$4.const$2.set(seg, x); - } - public static int stream_id$get(MemorySegment seg, long index) { - return (int)constants$4.const$2.get(seg.asSlice(index*sizeof())); + public static void error_count(MemorySegment struct, int fieldValue) { + struct.set(error_count$LAYOUT, error_count$OFFSET, fieldValue); } - public static void stream_id$set(MemorySegment seg, long index, int x) { - constants$4.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt signr$LAYOUT = (OfInt)$LAYOUT.select(groupElement("signr")); + + /** + * Layout for field: + * {@snippet lang=c : + * unsigned int signr + * } + */ + public static final OfInt signr$layout() { + return signr$LAYOUT; } - public static VarHandle error_count$VH() { - return constants$4.const$3; + + private static final long signr$OFFSET = $LAYOUT.byteOffset(groupElement("signr")); + + /** + * Offset for field: + * {@snippet lang=c : + * unsigned int signr + * } + */ + public static final long signr$offset() { + return signr$OFFSET; } + /** * Getter for field: - * {@snippet : - * int error_count; + * {@snippet lang=c : + * unsigned int signr * } */ - public static int error_count$get(MemorySegment seg) { - return (int)constants$4.const$3.get(seg); + public static int signr(MemorySegment struct) { + return struct.get(signr$LAYOUT, signr$OFFSET); } + /** * Setter for field: - * {@snippet : - * int error_count; + * {@snippet lang=c : + * unsigned int signr * } */ - public static void error_count$set(MemorySegment seg, int x) { - constants$4.const$3.set(seg, x); + public static void signr(MemorySegment struct, int fieldValue) { + struct.set(signr$LAYOUT, signr$OFFSET, fieldValue); } - public static int error_count$get(MemorySegment seg, long index) { - return (int)constants$4.const$3.get(seg.asSlice(index*sizeof())); - } - public static void error_count$set(MemorySegment seg, long index, int x) { - constants$4.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout usercontext$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("usercontext")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *usercontext + * } + */ + public static final AddressLayout usercontext$layout() { + return usercontext$LAYOUT; } - public static VarHandle signr$VH() { - return constants$4.const$4; + + private static final long usercontext$OFFSET = $LAYOUT.byteOffset(groupElement("usercontext")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *usercontext + * } + */ + public static final long usercontext$offset() { + return usercontext$OFFSET; } + /** * Getter for field: - * {@snippet : - * unsigned int signr; + * {@snippet lang=c : + * void *usercontext * } */ - public static int signr$get(MemorySegment seg) { - return (int)constants$4.const$4.get(seg); + public static MemorySegment usercontext(MemorySegment struct) { + return struct.get(usercontext$LAYOUT, usercontext$OFFSET); } + /** * Setter for field: - * {@snippet : - * unsigned int signr; + * {@snippet lang=c : + * void *usercontext * } */ - public static void signr$set(MemorySegment seg, int x) { - constants$4.const$4.set(seg, x); - } - public static int signr$get(MemorySegment seg, long index) { - return (int)constants$4.const$4.get(seg.asSlice(index*sizeof())); + public static void usercontext(MemorySegment struct, MemorySegment fieldValue) { + struct.set(usercontext$LAYOUT, usercontext$OFFSET, fieldValue); } - public static void signr$set(MemorySegment seg, long index, int x) { - constants$4.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final SequenceLayout iso_frame_desc$LAYOUT = (SequenceLayout)$LAYOUT.select(groupElement("iso_frame_desc")); + + /** + * Layout for field: + * {@snippet lang=c : + * struct usbdevfs_iso_packet_desc iso_frame_desc[] + * } + */ + public static final SequenceLayout iso_frame_desc$layout() { + return iso_frame_desc$LAYOUT; } - public static VarHandle usercontext$VH() { - return constants$4.const$5; + + private static final long iso_frame_desc$OFFSET = $LAYOUT.byteOffset(groupElement("iso_frame_desc")); + + /** + * Offset for field: + * {@snippet lang=c : + * struct usbdevfs_iso_packet_desc iso_frame_desc[] + * } + */ + public static final long iso_frame_desc$offset() { + return iso_frame_desc$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* usercontext; + * {@snippet lang=c : + * struct usbdevfs_iso_packet_desc iso_frame_desc[] * } */ - public static MemorySegment usercontext$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$4.const$5.get(seg); + public static MemorySegment iso_frame_desc(MemorySegment struct) { + return struct.asSlice(iso_frame_desc$OFFSET, iso_frame_desc$LAYOUT.byteSize()); } + /** * Setter for field: - * {@snippet : - * void* usercontext; + * {@snippet lang=c : + * struct usbdevfs_iso_packet_desc iso_frame_desc[] * } */ - public static void usercontext$set(MemorySegment seg, MemorySegment x) { - constants$4.const$5.set(seg, x); + public static void iso_frame_desc(MemorySegment struct, MemorySegment fieldValue) { + MemorySegment.copy(fieldValue, 0L, struct, iso_frame_desc$OFFSET, iso_frame_desc$LAYOUT.byteSize()); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static MemorySegment usercontext$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$4.const$5.get(seg.asSlice(index*sizeof())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static void usercontext$set(MemorySegment seg, long index, MemorySegment x) { - constants$4.const$5.set(seg.asSlice(index*sizeof()), x); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs$shared.java new file mode 100644 index 00000000..bdf645da --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.linux.gen.usbdevice_fs; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class usbdevice_fs$shared { + + usbdevice_fs$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs.java b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs.java index 68d05fef..8521d71b 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/linux/gen/usbdevice_fs/usbdevice_fs.java @@ -2,59 +2,71 @@ package net.codecrete.usb.linux.gen.usbdevice_fs; -import java.lang.foreign.AddressLayout; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class usbdevice_fs { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class usbdevice_fs extends usbdevice_fs$shared { + + usbdevice_fs() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + private static final int USBDEVFS_URB_TYPE_ISO = (int)0L; /** - * {@snippet : + * {@snippet lang=c : * #define USBDEVFS_URB_TYPE_ISO 0 * } */ public static int USBDEVFS_URB_TYPE_ISO() { - return (int)0L; + return USBDEVFS_URB_TYPE_ISO; } + private static final int USBDEVFS_URB_TYPE_INTERRUPT = (int)1L; /** - * {@snippet : + * {@snippet lang=c : * #define USBDEVFS_URB_TYPE_INTERRUPT 1 * } */ public static int USBDEVFS_URB_TYPE_INTERRUPT() { - return (int)1L; + return USBDEVFS_URB_TYPE_INTERRUPT; } + private static final int USBDEVFS_URB_TYPE_CONTROL = (int)2L; /** - * {@snippet : + * {@snippet lang=c : * #define USBDEVFS_URB_TYPE_CONTROL 2 * } */ public static int USBDEVFS_URB_TYPE_CONTROL() { - return (int)2L; + return USBDEVFS_URB_TYPE_CONTROL; } + private static final int USBDEVFS_URB_TYPE_BULK = (int)3L; /** - * {@snippet : + * {@snippet lang=c : * #define USBDEVFS_URB_TYPE_BULK 3 * } */ public static int USBDEVFS_URB_TYPE_BULK() { - return (int)3L; + return USBDEVFS_URB_TYPE_BULK; } + private static final int USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER = (int)2L; /** - * {@snippet : + * {@snippet lang=c : * #define USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 2 * } */ public static int USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER() { - return (int)2L; + return USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/CoreFoundationHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/CoreFoundationHelper.java index 74459d50..206d7a63 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/CoreFoundationHelper.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/CoreFoundationHelper.java @@ -35,10 +35,10 @@ private CoreFoundationHelper() { static String stringFromCFStringRef(MemorySegment string, Arena arena) { var strLen = CoreFoundation.CFStringGetLength(string); - var buffer = arena.allocateArray(JAVA_CHAR, strLen); + var buffer = arena.allocate(JAVA_CHAR, strLen); var range = CFRange.allocate(arena); - CFRange.location$set(range, 0); - CFRange.length$set(range, strLen); + CFRange.location(range, 0); + CFRange.length(range, strLen); CoreFoundation.CFStringGetCharacters(string, range, buffer); return new String(buffer.toArray(JAVA_CHAR)); } @@ -56,7 +56,7 @@ static String stringFromCFStringRef(MemorySegment string, Arena arena) { */ static MemorySegment createCFStringRef(String string, SegmentAllocator allocator) { var charArray = string.toCharArray(); - var chars = allocator.allocateArray(JAVA_CHAR, charArray.length); + var chars = allocator.allocate(JAVA_CHAR, charArray.length); chars.copyFrom(MemorySegment.ofArray(charArray)); return CoreFoundation.CFStringCreateWithCharacters(NULL, chars, string.length()); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitHelper.java index b508a015..08d35279 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitHelper.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitHelper.java @@ -93,7 +93,7 @@ private IoKitHelper() { * @return vtable */ static MemorySegment getVtable(MemorySegment self) { - return (MemorySegment) vtable$VH.get(self); + return (MemorySegment) vtable$VH.get(self, 0); } /** @@ -111,9 +111,9 @@ static MemorySegment getVtable(MemorySegment self) { static MemorySegment getInterface(int service, MemorySegment pluginType, MemorySegment interfaceId) { try (var arena = Arena.ofConfined()) { // MemorySegment for holding IOCFPlugInInterface** - var plugHolder = arena.allocate(ADDRESS, NULL); + var plugHolder = arena.allocate(ADDRESS); // MemorySegment for holding score - var score = arena.allocate(JAVA_INT, 0); + var score = arena.allocate(JAVA_INT); var ret = IOKit.IOCreatePlugInInterfaceForService(service, pluginType, kIOCFPlugInInterfaceID, plugHolder , score); if (ret != 0) @@ -123,9 +123,9 @@ static MemorySegment getInterface(int service, MemorySegment pluginType, MemoryS // UUID bytes var refiid = CoreFoundation.CFUUIDGetUUIDBytes(arena, interfaceId); // MemorySegment for holding xxxInterface** - var intfHolder = arena.allocate(ADDRESS, NULL); - ret = IoKitUSB.QueryInterface(plug, refiid, intfHolder); - IoKitUSB.Release(plug); + var intfHolder = arena.allocate(ADDRESS); + ret = IoKitUsb.QueryInterface(plug, refiid, intfHolder); + IoKitUsb.Release(plug); if (ret != 0) return null; return dereference(intfHolder, COM_OBJECT); @@ -152,7 +152,7 @@ static Integer getPropertyInt(int service, MemorySegment key, Arena arena) { Integer result = null; var type = CoreFoundation.CFGetTypeID(value); if (type == CoreFoundation.CFNumberGetTypeID()) { - var numberValue = arena.allocate(JAVA_INT, 0); + var numberValue = arena.allocate(JAVA_INT); if (CoreFoundation.CFNumberGetValue(value, CoreFoundation.kCFNumberSInt32Type(), numberValue) != 0) result = numberValue.get(JAVA_INT, 0); } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUSB.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUsb.java similarity index 60% rename from java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUSB.java rename to java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUsb.java index 2ba04f12..b1fd6fbe 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUSB.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUsb.java @@ -10,7 +10,6 @@ import net.codecrete.usb.macos.gen.iokit.IOUSBDeviceStruct187; import net.codecrete.usb.macos.gen.iokit.IOUSBInterfaceStruct190; -import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import static net.codecrete.usb.macos.IoKitHelper.getVtable; @@ -19,169 +18,169 @@ * Helper functions to call the virtual methods of IOKit USB interfaces. */ @SuppressWarnings({"java:S100", "java:S107", "UnusedReturnValue", "SameParameterValue"}) -class IoKitUSB { +class IoKitUsb { - private IoKitUSB() { + private IoKitUsb() { } // HRESULT (STDMETHODCALLTYPE *QueryInterface)(void *thisPointer, REFIID iid, LPVOID *ppv) static int QueryInterface(MemorySegment self, MemorySegment iid, MemorySegment ppv) { - return IOUSBDeviceStruct187.QueryInterface(getVtable(self), Arena.global()).apply(self, iid, ppv); + return IOUSBDeviceStruct187.QueryInterface.invoke(IOUSBDeviceStruct187.QueryInterface(getVtable(self)), self, iid, ppv); } // ULONG (STDMETHODCALLTYPE *AddRef)(void *thisPointer) static int AddRef(MemorySegment self) { - return IOUSBDeviceStruct187.AddRef(getVtable(self), Arena.global()).apply(self); + return IOUSBDeviceStruct187.AddRef.invoke(IOUSBDeviceStruct187.AddRef(getVtable(self)), self); } // ULONG (STDMETHODCALLTYPE *Release)(void *thisPointer) static int Release(MemorySegment self) { - return IOUSBDeviceStruct187.Release(getVtable(self), Arena.global()).apply(self); + return IOUSBDeviceStruct187.Release.invoke(IOUSBDeviceStruct187.Release(getVtable(self)), self); } // IOReturn (* CreateDeviceAsyncEventSource)(void* self, CFRunLoopSourceRef* source) static int CreateDeviceAsyncEventSource(MemorySegment self, MemorySegment source) { - return IOUSBDeviceStruct187.CreateDeviceAsyncEventSource(getVtable(self), Arena.global()).apply(self, + return IOUSBDeviceStruct187.CreateDeviceAsyncEventSource.invoke(IOUSBDeviceStruct187.CreateDeviceAsyncEventSource(getVtable(self)), self, source); } // CFRunLoopSourceRef (* GetDeviceAsyncEventSource)(void* self) static MemorySegment GetDeviceAsyncEventSource(MemorySegment self) { - return IOUSBDeviceStruct187.GetDeviceAsyncEventSource(getVtable(self), Arena.global()).apply(self); + return IOUSBDeviceStruct187.GetDeviceAsyncEventSource.invoke(IOUSBDeviceStruct187.GetDeviceAsyncEventSource(getVtable(self)), self); } // IOReturn (*USBDeviceOpenSeize)(void *self) static int USBDeviceOpenSeize(MemorySegment self) { - return IOUSBDeviceStruct187.USBDeviceOpenSeize(getVtable(self), Arena.global()).apply(self); + return IOUSBDeviceStruct187.USBDeviceOpenSeize.invoke(IOUSBDeviceStruct187.USBDeviceOpenSeize(getVtable(self)), self); } // IOReturn (*USBDeviceClose)(void *self) static int USBDeviceClose(MemorySegment self) { - return IOUSBDeviceStruct187.USBDeviceClose(getVtable(self), Arena.global()).apply(self); + return IOUSBDeviceStruct187.USBDeviceClose.invoke(IOUSBDeviceStruct187.USBDeviceClose(getVtable(self)), self); } // IOReturn (* USBDeviceReEnumerate)(void* self, UInt32 options) static int USBDeviceReEnumerate(MemorySegment self, int options) { - return IOUSBDeviceStruct187.USBDeviceReEnumerate(getVtable(self), Arena.global()).apply(self, options); + return IOUSBDeviceStruct187.USBDeviceReEnumerate.invoke(IOUSBDeviceStruct187.USBDeviceReEnumerate(getVtable(self)), self, options); } // IOReturn (*GetConfigurationDescriptorPtr)(void *self, UInt8 configIndex, IOUSBConfigurationDescriptorPtr *desc) static int GetConfigurationDescriptorPtr(MemorySegment self, byte configIndex, MemorySegment descHolder) { - return IOUSBDeviceStruct187.GetConfigurationDescriptorPtr(getVtable(self), Arena.global()).apply(self, + return IOUSBDeviceStruct187.GetConfigurationDescriptorPtr.invoke(IOUSBDeviceStruct187.GetConfigurationDescriptorPtr(getVtable(self)), self, configIndex, descHolder); } // IOReturn (*SetConfiguration)(void *self, UInt8 configNum) static int SetConfiguration(MemorySegment self, byte configValue) { - return IOUSBDeviceStruct187.SetConfiguration(getVtable(self), Arena.global()).apply(self, configValue); + return IOUSBDeviceStruct187.SetConfiguration.invoke(IOUSBDeviceStruct187.SetConfiguration(getVtable(self)), self, configValue); } // IOReturn (*CreateInterfaceIterator)(void *self, IOUSBFindInterfaceRequest *req, io_iterator_t *iter) static int CreateInterfaceIterator(MemorySegment self, MemorySegment req, MemorySegment iter) { - return IOUSBDeviceStruct187.CreateInterfaceIterator(getVtable(self), Arena.global()).apply(self, req, iter); + return IOUSBDeviceStruct187.CreateInterfaceIterator.invoke(IOUSBDeviceStruct187.CreateInterfaceIterator(getVtable(self)), self, req, iter); } // IOReturn (* DeviceRequest)(void* self, IOUSBDevRequest* req) static int DeviceRequest(MemorySegment self, MemorySegment deviceRequest) { - return IOUSBDeviceStruct187.DeviceRequest(getVtable(self), Arena.global()).apply(self, deviceRequest); + return IOUSBDeviceStruct187.DeviceRequest.invoke(IOUSBDeviceStruct187.DeviceRequest(getVtable(self)), self, deviceRequest); } // IOReturn (* DeviceRequestAsync)(void* self, IOUSBDevRequest* req, IOAsyncCallback1 callback, void* refCon) static int DeviceRequestAsync(MemorySegment self, MemorySegment deviceRequest, MemorySegment callback, MemorySegment refCon) { - return IOUSBDeviceStruct187.DeviceRequestAsync(getVtable(self), Arena.global()).apply(self, deviceRequest, + return IOUSBDeviceStruct187.DeviceRequestAsync.invoke(IOUSBDeviceStruct187.DeviceRequestAsync(getVtable(self)), self, deviceRequest, callback, refCon); } // IOReturn (*USBInterfaceOpen)(void *self) static int USBInterfaceOpen(MemorySegment self) { - return IOUSBInterfaceStruct190.USBInterfaceOpen(getVtable(self), Arena.global()).apply(self); + return IOUSBInterfaceStruct190.USBInterfaceOpen.invoke(IOUSBInterfaceStruct190.USBInterfaceOpen(getVtable(self)), self); } // IOReturn (*USBInterfaceClose)(void *self) static int USBInterfaceClose(MemorySegment self) { - return IOUSBInterfaceStruct190.USBInterfaceClose(getVtable(self), Arena.global()).apply(self); + return IOUSBInterfaceStruct190.USBInterfaceClose.invoke(IOUSBInterfaceStruct190.USBInterfaceClose(getVtable(self)), self); } // IOReturn (*GetInterfaceNumber)(void *self, UInt8 *intfNumber) static int GetInterfaceNumber(MemorySegment self, MemorySegment intfNumberHolder) { - return IOUSBInterfaceStruct190.GetInterfaceNumber(getVtable(self), Arena.global()).apply(self, + return IOUSBInterfaceStruct190.GetInterfaceNumber.invoke(IOUSBInterfaceStruct190.GetInterfaceNumber(getVtable(self)), self, intfNumberHolder); } // IOReturn (*GetNumEndpoints)(void *self, UInt8 *intfNumEndpoints) static int GetNumEndpoints(MemorySegment self, MemorySegment intfNumEndpointsHolder) { - return IOUSBInterfaceStruct190.GetNumEndpoints(getVtable(self), Arena.global()).apply(self, + return IOUSBInterfaceStruct190.GetNumEndpoints.invoke(IOUSBInterfaceStruct190.GetNumEndpoints(getVtable(self)), self, intfNumEndpointsHolder); } // IOReturn (*GetPipeProperties)(void *self, UInt8 pipeRef, UInt8 *direction, UInt8 *number, UInt8 *transferType, // UInt16 *maxPacketSize, UInt8 *interval) static int GetPipeProperties(MemorySegment self, byte pipeRef, MemorySegment directionHolder, - MemorySegment numberHolder, MemorySegment transferTypeHolder, - MemorySegment maxPacketSizeHolder, MemorySegment intervalHolder) { - return IOUSBInterfaceStruct190.GetPipeProperties(getVtable(self), Arena.global()).apply(self, pipeRef, + MemorySegment numberHolder, MemorySegment transferTypeHolder, + MemorySegment maxPacketSizeHolder, MemorySegment intervalHolder) { + return IOUSBInterfaceStruct190.GetPipeProperties.invoke(IOUSBInterfaceStruct190.GetPipeProperties(getVtable(self)), self, pipeRef, directionHolder, numberHolder, transferTypeHolder, maxPacketSizeHolder, intervalHolder); } // IOReturn (*ReadPipeAsync)(void *self, UInt8 pipeRef, void *buf, UInt32 size, IOAsyncCallback1 callback, void // *refcon) static int ReadPipeAsync(MemorySegment self, byte pipeRef, MemorySegment buf, int size, - MemorySegment callback, MemorySegment refcon) { - return IOUSBInterfaceStruct190.ReadPipeAsync(getVtable(self), Arena.global()).apply(self, pipeRef, buf, + MemorySegment callback, MemorySegment refcon) { + return IOUSBInterfaceStruct190.ReadPipeAsync.invoke(IOUSBInterfaceStruct190.ReadPipeAsync(getVtable(self)), self, pipeRef, buf, size, callback, refcon); } // IOReturn (*ReadPipeAsyncTO)(void *self, UInt8 pipeRef, void *buf, UInt32 size, UInt32 noDataTimeout, UInt32 // completionTimeout, IOAsyncCallback1 callback, void *refcon) static int ReadPipeAsyncTO(MemorySegment self, byte pipeRef, MemorySegment buf, int size, - int noDataTimeout, int completionTimeout, MemorySegment callback, - MemorySegment refcon) { - return IOUSBInterfaceStruct190.ReadPipeAsyncTO(getVtable(self), Arena.global()).apply(self, pipeRef, buf, + int noDataTimeout, int completionTimeout, MemorySegment callback, + MemorySegment refcon) { + return IOUSBInterfaceStruct190.ReadPipeAsyncTO.invoke(IOUSBInterfaceStruct190.ReadPipeAsyncTO(getVtable(self)), self, pipeRef, buf, size, noDataTimeout, completionTimeout, callback, refcon); } // IOReturn (*WritePipeAsync)(vovoid *self, UInt8 pipeRef, void *buf, UInt32 size, IOAsyncCallback1 callback, // void *refcon) static int WritePipeAsync(MemorySegment self, byte pipeRef, MemorySegment buf, int size, - MemorySegment callback, MemorySegment refcon) { - return IOUSBInterfaceStruct190.WritePipeAsync(getVtable(self), Arena.global()).apply(self, pipeRef, buf, + MemorySegment callback, MemorySegment refcon) { + return IOUSBInterfaceStruct190.WritePipeAsync.invoke(IOUSBInterfaceStruct190.WritePipeAsync(getVtable(self)), self, pipeRef, buf, size, callback, refcon); } // IOReturn (*WritePipeAsyncTO)(void *self, UInt8 pipeRef, void *buf, UInt32 size, UInt32 noDataTimeout, UInt32 // completionTimeout, IOAsyncCallback1 callback, void *refcon) static int WritePipeAsyncTO(MemorySegment self, byte pipeRef, MemorySegment buf, int size, - int noDataTimeout, int completionTimeout, MemorySegment callback, - MemorySegment refcon) { - return IOUSBInterfaceStruct190.WritePipeAsyncTO(getVtable(self), Arena.global()).apply(self, pipeRef, buf, + int noDataTimeout, int completionTimeout, MemorySegment callback, + MemorySegment refcon) { + return IOUSBInterfaceStruct190.WritePipeAsyncTO.invoke(IOUSBInterfaceStruct190.WritePipeAsyncTO(getVtable(self)), self, pipeRef, buf, size, noDataTimeout, completionTimeout, callback, refcon); } // IOReturn (* AbortPipe)(void* self, UInt8 pipeRef) static int AbortPipe(MemorySegment self, byte pipeRef) { - return IOUSBInterfaceStruct190.AbortPipe(getVtable(self), Arena.global()).apply(self, pipeRef); + return IOUSBInterfaceStruct190.AbortPipe.invoke(IOUSBInterfaceStruct190.AbortPipe(getVtable(self)), self, pipeRef); } // IOReturn (*SetAlternateInterface)(void *self, UInt8 alternateSetting) static int SetAlternateInterface(MemorySegment self, byte alternateSetting) { - return IOUSBInterfaceStruct190.SetAlternateInterface(getVtable(self), Arena.global()).apply(self, + return IOUSBInterfaceStruct190.SetAlternateInterface.invoke(IOUSBInterfaceStruct190.SetAlternateInterface(getVtable(self)), self, alternateSetting); } // IOReturn (* ClearPipeStallBothEnds)(void* self, UInt8 pipeRef) static int ClearPipeStallBothEnds(MemorySegment self, byte pipeRef) { - return IOUSBInterfaceStruct190.ClearPipeStallBothEnds(getVtable(self), Arena.global()).apply(self, pipeRef); + return IOUSBInterfaceStruct190.ClearPipeStallBothEnds.invoke(IOUSBInterfaceStruct190.ClearPipeStallBothEnds(getVtable(self)), self, pipeRef); } // CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void* self) static MemorySegment GetInterfaceAsyncEventSource(MemorySegment self) { - return IOUSBInterfaceStruct190.GetInterfaceAsyncEventSource(getVtable(self), Arena.global()).apply(self); + return IOUSBInterfaceStruct190.GetInterfaceAsyncEventSource.invoke(IOUSBInterfaceStruct190.GetInterfaceAsyncEventSource(getVtable(self)), self); } // IOReturn (*CreateInterfaceAsyncEventSource)(void *self, CFRunLoopSourceRef *source) static int CreateInterfaceAsyncEventSource(MemorySegment self, MemorySegment source) { - return IOUSBInterfaceStruct190.CreateInterfaceAsyncEventSource(getVtable(self), Arena.global()).apply(self + return IOUSBInterfaceStruct190.CreateInterfaceAsyncEventSource.invoke(IOUSBInterfaceStruct190.CreateInterfaceAsyncEventSource(getVtable(self)), self , source); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosAsyncTask.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosAsyncTask.java index 0ca192b5..b4b71b62 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosAsyncTask.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosAsyncTask.java @@ -7,7 +7,8 @@ package net.codecrete.usb.macos; -import net.codecrete.usb.USBException; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.macos.gen.corefoundation.CFMessagePortCreateLocal$callout; import net.codecrete.usb.macos.gen.corefoundation.CoreFoundation; import net.codecrete.usb.macos.gen.iokit.IOKit; @@ -22,8 +23,14 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; +import static java.lang.System.Logger.Level.ERROR; +import static java.lang.System.Logger.Level.WARNING; +import static java.lang.foreign.MemorySegment.NULL; import static java.lang.foreign.ValueLayout.ADDRESS; import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED; + /** * Background task for handling asynchronous transfers. @@ -49,11 +56,14 @@ enum TaskState { */ static final MacosAsyncTask INSTANCE = new MacosAsyncTask(); + private static final System.Logger LOG = System.getLogger(MacosAsyncTask.class.getName()); + private final ReentrantLock asyncIoLock = new ReentrantLock(); private final Condition asyncIoReady = asyncIoLock.newCondition(); private TaskState state = TaskState.NOT_STARTED; private MemorySegment asyncIoRunLoop; private MemorySegment completionUpcallStub; + private MemorySegment messagePort; private long lastTransferId; private final Map transfersById = new HashMap<>(); @@ -67,18 +77,12 @@ void addEventSource(MemorySegment source) { asyncIoLock.lock(); if (state != TaskState.RUNNING) { - if (state == TaskState.NOT_STARTED) { - startAsyncIOThread(source); - waitForRunLoopReady(); - return; - - } else { - // special case: run loop is not ready yet but background process is already starting - waitForRunLoopReady(); - } + if (state == TaskState.NOT_STARTED) + startAsyncIOThread(); + waitForRunLoopReady(); } - CoreFoundation.CFRunLoopAddSource(asyncIoRunLoop, source, IOKit.kCFRunLoopDefaultMode$get()); + CoreFoundation.CFRunLoopAddSource(asyncIoRunLoop, source, IOKit.kCFRunLoopDefaultMode()); } finally { asyncIoLock.unlock(); @@ -92,34 +96,72 @@ private void waitForRunLoopReady() { /** * Removes an event source from this background task. - * + *

+ * The event source is not immediately removed. Instead, it is posted to a message queue + * processed by the same background thread processing the completion callbacks. This ensures + * that the events from releasing interfaces and closing devices are processed. + *

* @param source event source */ void removeEventSource(MemorySegment source) { - CoreFoundation.CFRunLoopRemoveSource(asyncIoRunLoop, source, IOKit.kCFRunLoopDefaultMode$get()); + try (var arena = Arena.ofConfined()) { + var eventSourceRef = arena.allocate(JAVA_LONG, 1); + eventSourceRef.set(JAVA_LONG, 0, source.address()); + var dataRef = CoreFoundation.CFDataCreate(NULL, eventSourceRef, eventSourceRef.byteSize()); + CoreFoundation.CFMessagePortSendRequest(messagePort, 0, dataRef, 0, 0, NULL, NULL); + CoreFoundation.CFRelease(dataRef); + } } /** * Starts the background thread. - * - * @param firstSource first event source */ - private void startAsyncIOThread(MemorySegment firstSource) { + @SuppressWarnings("java:S125") + private void startAsyncIOThread() { + MemorySegment messagePortSource = NULL; + MemorySegment localPort = NULL; + try { state = TaskState.STARTING; + + // create descriptor for completion callback function var completionHandlerFuncDesc = FunctionDescriptor.ofVoid(ADDRESS, JAVA_INT, ADDRESS); var asyncIOCompletedMH = MethodHandles.lookup().findVirtual(MacosAsyncTask.class, "asyncIOCompleted", MethodType.methodType(void.class, MemorySegment.class, int.class, MemorySegment.class)); - var methodHandle = asyncIOCompletedMH.bindTo(this); - completionUpcallStub = Linker.nativeLinker().upcallStub(methodHandle, completionHandlerFuncDesc, - Arena.global()); + completionUpcallStub = Linker.nativeLinker().upcallStub(methodHandle, completionHandlerFuncDesc, Arena.global()); + + // create local and remote message ports (all three CF creations can return NULL, + // e.g. if bootstrap port registration fails in a sandboxed process) + var pid = ProcessHandle.current().pid(); + var portName = CoreFoundationHelper.createCFStringRef("net.codecrete.usb.macos.eventsource." + pid, Arena.global()); + var messagePortCallback = CFMessagePortCreateLocal$callout.allocate(this::messagePortCallback, Arena.global()); + localPort = CoreFoundation.CFMessagePortCreateLocal(NULL, portName, messagePortCallback, NULL, NULL); + if (localPort.address() == 0) + throw new UsbException("internal error (CFMessagePortCreateLocal failed)"); + messagePortSource = CoreFoundation.CFMessagePortCreateRunLoopSource(NULL, localPort, 0); + if (messagePortSource.address() == 0) + throw new UsbException("internal error (CFMessagePortCreateRunLoopSource failed)"); + var remotePort = CoreFoundation.CFMessagePortCreateRemote(NULL, portName); + if (remotePort.address() == 0) + throw new UsbException("internal error (CFMessagePortCreateRemote failed)"); + messagePort = remotePort; - } catch (IllegalAccessException | NoSuchMethodException e) { - throw new USBException("internal error (creating method handle)", e); + } catch (Exception e) { + // release partially created ports and reset the state; otherwise the task would be + // stuck in STARTING and all later addEventSource() calls would wait forever + if (messagePortSource.address() != 0) + CoreFoundation.CFRelease(messagePortSource); + if (localPort.address() != 0) + CoreFoundation.CFRelease(localPort); + state = TaskState.NOT_STARTED; + if (e instanceof RuntimeException runtimeException) + throw runtimeException; + throw new UsbException("internal error (creating method handle)", e); } - var thread = new Thread(() -> asyncIOCompletionTask(firstSource), "USB async IO"); + var source = messagePortSource; + var thread = new Thread(() -> asyncIOCompletionTask(source), "USB async IO"); thread.setDaemon(true); thread.start(); } @@ -137,7 +179,7 @@ private void asyncIOCompletionTask(MemorySegment firstSource) { try { asyncIoLock.lock(); asyncIoRunLoop = CoreFoundation.CFRunLoopGetCurrent(); - CoreFoundation.CFRunLoopAddSource(asyncIoRunLoop, firstSource, IOKit.kCFRunLoopDefaultMode$get()); + CoreFoundation.CFRunLoopAddSource(asyncIoRunLoop, firstSource, IOKit.kCFRunLoopDefaultMode()); state = TaskState.RUNNING; asyncIoReady.signalAll(); } finally { @@ -146,6 +188,7 @@ private void asyncIOCompletionTask(MemorySegment firstSource) { // loop forever CoreFoundation.CFRunLoopRun(); + LOG.log(WARNING, "unexpected end of CFRunLoopRun"); } /** @@ -164,6 +207,20 @@ synchronized void prepareForSubmission(MacosTransfer transfer) { transfersById.put(lastTransferId, transfer); } + /** + * Undoes the registration performed by {@link #prepareForSubmission(MacosTransfer)}. + *

+ * Must be called if the native submission of a prepared transfer fails. In that case, + * no completion callback will ever fire for the transfer, so its map entry would leak + * unless it is removed here. + *

+ * + * @param transfer transfer whose submission failed + */ + synchronized void submissionFailed(MacosTransfer transfer) { + transfersById.remove(transfer.id()); + } + /** * Callback function called when an asynchronous transfer has completed. * @@ -174,14 +231,43 @@ synchronized void prepareForSubmission(MacosTransfer transfer) { @SuppressWarnings("java:S1144") private void asyncIOCompleted(MemorySegment refcon, int result, MemorySegment arg0) { - MacosTransfer transfer; - synchronized (this) { - transfer = transfersById.remove(refcon.address()); + try { + MacosTransfer transfer; + synchronized (this) { + transfer = transfersById.remove(refcon.address()); + } + + if (transfer == null) { + // A completion for an unknown transfer ID (e.g. a duplicate or spurious + // callback). Ignore it rather than dereferencing null. + LOG.log(WARNING, "Ignoring async IO completion for unknown transfer ID {0}", refcon.address()); + return; + } + + transfer.setResultCode(result); + transfer.setResultSize((int) arg0.address()); + transfer.completion().completed(transfer); + + } catch (Exception e) { + // This method is a native upcall running on the process-wide async IO thread. + // Any exception escaping into CFRunLoopRun() would kill that thread and hang + // all async transfers for the entire library, so nothing must escape here. + LOG.log(ERROR, "Unexpected exception while handling async IO completion", e); } + } - transfer.setResultCode(result); - transfer.setResultSize((int) arg0.address()); - transfer.completion().completed(transfer); + /** + * Callback function called when a message is received on the message port. + *

+ * All messages are related to removing event sources. They just contain the run loop source reference. + *

+ */ + @SuppressWarnings({"java:S1144", "unused"}) + private MemorySegment messagePortCallback(MemorySegment local, int msgid, MemorySegment data, MemorySegment info) { + var runloopSourceRefPtr = CoreFoundation.CFDataGetBytePtr(data); + var runloopSourceRef = MemorySegment.ofAddress(runloopSourceRefPtr.get(JAVA_LONG_UNALIGNED, 0)); + CoreFoundation.CFRunLoopRemoveSource(asyncIoRunLoop, runloopSourceRef, IOKit.kCFRunLoopDefaultMode()); + return NULL; } /** diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointInputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointInputStream.java index e947caec..06dff333 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointInputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointInputStream.java @@ -12,12 +12,12 @@ public class MacosEndpointInputStream extends EndpointInputStream { - MacosEndpointInputStream(MacosUSBDevice device, int endpointNumber, int bufferSize) { + MacosEndpointInputStream(MacosUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferIn(Transfer transfer) { - ((MacosUSBDevice) device).submitTransferIn(endpointNumber, (MacosTransfer) transfer, 0); + ((MacosUsbDevice) device).submitTransferIn(endpointNumber, (MacosTransfer) transfer, 0); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointOutputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointOutputStream.java index d8f16f2c..898ab5e1 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointOutputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosEndpointOutputStream.java @@ -12,12 +12,12 @@ public class MacosEndpointOutputStream extends EndpointOutputStream { - MacosEndpointOutputStream(MacosUSBDevice device, int endpointNumber, int bufferSize) { + MacosEndpointOutputStream(MacosUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferOut(Transfer request) { - ((MacosUSBDevice) device).submitTransferOut(endpointNumber, (MacosTransfer) request, 0); + ((MacosUsbDevice) device).submitTransferOut(endpointNumber, (MacosTransfer) request, 0); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDevice.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDevice.java similarity index 60% rename from java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDevice.java rename to java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDevice.java index 18673d2c..57065c7c 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDevice.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDevice.java @@ -7,15 +7,21 @@ package net.codecrete.usb.macos; -import net.codecrete.usb.*; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbRecipient; +import net.codecrete.usb.UsbRequestType; +import net.codecrete.usb.UsbTransferType; import net.codecrete.usb.common.ScopeCleanup; import net.codecrete.usb.common.Transfer; -import net.codecrete.usb.common.USBDeviceImpl; +import net.codecrete.usb.common.UsbDeviceImpl; import net.codecrete.usb.macos.gen.iokit.IOKit; import net.codecrete.usb.macos.gen.iokit.IOUSBDevRequest; import net.codecrete.usb.macos.gen.iokit.IOUSBFindInterfaceRequest; import net.codecrete.usb.usbstandard.ConfigurationDescriptor; import net.codecrete.usb.usbstandard.Constants; +import org.jetbrains.annotations.NotNull; import java.io.InputStream; import java.io.OutputStream; @@ -26,12 +32,15 @@ import java.util.List; import java.util.Map; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; import static net.codecrete.usb.common.ForeignMemory.dereference; -import static net.codecrete.usb.macos.MacosUSBException.throwException; +import static net.codecrete.usb.macos.MacosUsbException.throwException; /** - * MacOS implementation of {@link net.codecrete.usb.USBDevice}. + * MacOS implementation of {@link UsbDevice}. *

* All read and write operations on endpoints are submitted through synchronized methods in order to control * concurrency. If it wasn't controlled, the danger is that device and interface pointers are used, which have @@ -42,8 +51,8 @@ * asynchronous transfer and waiting for the completion. *

*/ -@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter", "java:S2160"}) -public class MacosUSBDevice extends USBDeviceImpl { +@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter", "java:S2160", "java:S3077"}) +public class MacosUsbDevice extends UsbDeviceImpl { private final MacosAsyncTask asyncTask; // Native USB device interface (IOUSBDeviceInterface**) @@ -51,13 +60,15 @@ public class MacosUSBDevice extends USBDeviceImpl { // Currently selected configuration private int configurationValue; // Details about interfaces that have been claimed - private List claimedInterfaces; + // (volatile: written under the device monitor, read unlocked via isOpened(); + // the list contents are only accessed while holding the device monitor) + private volatile List claimedInterfaces; // Details about endpoints of current alternate settings (for claimed interfaces) private Map endpoints; private final long discoveryTime; - MacosUSBDevice(MemorySegment device, Object id, int vendorId, int productId) { + MacosUsbDevice(MemorySegment device, Object id, int vendorId, int productId) { super(id, vendorId, productId); discoveryTime = System.currentTimeMillis(); asyncTask = MacosAsyncTask.INSTANCE; @@ -65,55 +76,58 @@ public class MacosUSBDevice extends USBDeviceImpl { loadDescription(device); this.device = device; - IoKitUSB.AddRef(device); + IoKitUsb.AddRef(device); } @Override - public void detachStandardDrivers() { - if (isOpen()) - throwException("detachStandardDrivers() must not be called while the device is open"); - var ret = IoKitUSB.USBDeviceReEnumerate(device, IOKit.kUSBReEnumerateCaptureDeviceMask()); + public synchronized void detachStandardDrivers() { + checkIsClosed("detachStandardDrivers() must not be called while the device is open"); + var ret = IoKitUsb.USBDeviceReEnumerate(device, IOKit.kUSBReEnumerateCaptureDeviceMask()); if (ret != 0) throwException(ret, "detaching standard drivers failed"); } @Override - public void attachStandardDrivers() { - if (isOpen()) - throwException("attachStandardDrivers() must not be called while the device is open"); - var ret = IoKitUSB.USBDeviceReEnumerate(device, IOKit.kUSBReEnumerateReleaseDeviceMask()); + public synchronized void attachStandardDrivers() { + checkIsClosed("attachStandardDrivers() must not be called while the device is open"); + var ret = IoKitUsb.USBDeviceReEnumerate(device, IOKit.kUSBReEnumerateReleaseDeviceMask()); if (ret != 0) throwException(ret, "attaching standard drivers failed"); } @Override - public boolean isOpen() { + public boolean isOpened() { return claimedInterfaces != null; } - @SuppressWarnings("java:S2276") + @SuppressWarnings({"java:S2276", "java:S2142"}) @Override public synchronized void open() { - if (isOpen()) - throwException("device is already open"); + checkIsClosed("device is already open"); // open device (several retries if device has just been connected/discovered) var duration = System.currentTimeMillis() - discoveryTime; var numTries = duration < 1000 ? 4 : 1; var ret = 0; + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // (which would make the remaining backoff sleeps throw immediately and defeat + // the retry delay). Re-assert once the retries are done. + var wasInterrupted = false; while (numTries > 0) { numTries -= 1; - ret = IoKitUSB.USBDeviceOpenSeize(device); + ret = IoKitUsb.USBDeviceOpenSeize(device); if (ret != IOKit.kIOReturnExclusiveAccess()) break; // sleep and retry try { Thread.sleep(90); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException _) { + wasInterrupted = true; } } + if (wasInterrupted) + Thread.currentThread().interrupt(); if (ret != 0) throwException(ret, "opening USB device failed"); @@ -121,7 +135,7 @@ public synchronized void open() { addDeviceEventSource(); // set configuration - ret = IoKitUSB.SetConfiguration(device, (byte) configurationValue); + ret = IoKitUsb.SetConfiguration(device, (byte) configurationValue); if (ret != 0) throwException(ret, "setting configuration failed"); @@ -130,28 +144,31 @@ public synchronized void open() { @Override public synchronized void close() { - if (!isOpen()) + if (!isOpened()) return; for (var interfaceInfo : claimedInterfaces) { - IoKitUSB.USBInterfaceClose(interfaceInfo.iokitInterface); - IoKitUSB.Release(interfaceInfo.iokitInterface); setClaimed(interfaceInfo.interfaceNumber, false); + var source = IoKitUsb.GetInterfaceAsyncEventSource(interfaceInfo.iokitInterface()); + IoKitUsb.USBInterfaceClose(interfaceInfo.iokitInterface); + IoKitUsb.Release(interfaceInfo.iokitInterface); + if (source.address() != 0) + asyncTask.removeEventSource(source); } claimedInterfaces = null; endpoints = null; - var source = IoKitUSB.GetDeviceAsyncEventSource(device); + var source = IoKitUsb.GetDeviceAsyncEventSource(device); + IoKitUsb.USBDeviceClose(device); if (source.address() != 0) asyncTask.removeEventSource(source); - - IoKitUSB.USBDeviceClose(device); } - synchronized void closeFully() { - close(); - IoKitUSB.Release(device); + @Override + protected synchronized void disconnect() { + super.disconnect(); + IoKitUsb.Release(device); device = null; } @@ -160,31 +177,36 @@ private void loadDescription(MemorySegment device) { // retrieve device descriptor using synchronous control transfer var data = arena.allocate(255); - var deviceRequest = createDeviceRequest(arena, USBDirection.IN, new USBControlTransfer( - USBRequestType.STANDARD, - USBRecipient.DEVICE, + var deviceRequest = createDeviceRequest(arena, UsbDirection.IN, new UsbControlTransfer( + UsbRequestType.STANDARD, + UsbRecipient.DEVICE, 6, // get descriptor Constants.DEVICE_DESCRIPTOR_TYPE << 8, 0 ), data); - var ret = IoKitUSB.DeviceRequest(device, deviceRequest); + var ret = IoKitUsb.DeviceRequest(device, deviceRequest); if (ret != 0) throwException(ret, "querying device descriptor failed"); - var len = IOUSBDevRequest.wLenDone$get(deviceRequest); + var len = IOUSBDevRequest.wLenDone(deviceRequest); rawDeviceDescriptor = data.asSlice(0, len).toArray(JAVA_BYTE); configurationValue = 0; // retrieve information of first configuration var descPtrHolder = arena.allocate(ADDRESS); - ret = IoKitUSB.GetConfigurationDescriptorPtr(device, (byte) 0, descPtrHolder); + ret = IoKitUsb.GetConfigurationDescriptorPtr(device, (byte) 0, descPtrHolder); if (ret != 0) throwException(ret, "querying first configuration failed"); - var configDesc = dereference(descPtrHolder).reinterpret(999999); - var configDescHeader = new ConfigurationDescriptor(configDesc); - configDesc = configDesc.asSlice(0, configDescHeader.totalLength()); + // read the descriptor header with a minimally sized view first, then resize to the + // total length the header reports (the kernel buffer was sized from the same field) + var headerSize = ConfigurationDescriptor.LAYOUT.byteSize(); + var configDescHeader = new ConfigurationDescriptor(dereference(descPtrHolder).reinterpret(headerSize)); + var totalLength = configDescHeader.totalLength(); + if (totalLength < headerSize) + throwException("invalid configuration descriptor (wTotalLength: %d)", totalLength); + var configDesc = dereference(descPtrHolder).reinterpret(totalLength); var configuration = setConfigurationDescriptor(configDesc); configurationValue = 255 & configuration.configValue(); @@ -192,17 +214,17 @@ private void loadDescription(MemorySegment device) { } @SuppressWarnings("java:S135") - private InterfaceInfo findInterface(int interfaceNumber) { + private InterfaceInfo findInterfaceInfo(int interfaceNumber) { try (var arena = Arena.ofConfined(); var outerCleanup = new ScopeCleanup()) { var request = IOUSBFindInterfaceRequest.allocate(arena); - IOUSBFindInterfaceRequest.bInterfaceClass$set(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); - IOUSBFindInterfaceRequest.bInterfaceSubClass$set(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); - IOUSBFindInterfaceRequest.bInterfaceProtocol$set(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); - IOUSBFindInterfaceRequest.bAlternateSetting$set(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); + IOUSBFindInterfaceRequest.bInterfaceClass(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); + IOUSBFindInterfaceRequest.bInterfaceSubClass(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); + IOUSBFindInterfaceRequest.bInterfaceProtocol(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); + IOUSBFindInterfaceRequest.bAlternateSetting(request, (short) IOKit.kIOUSBFindInterfaceDontCare()); var iterHolder = arena.allocate(JAVA_INT); - var ret = IoKitUSB.CreateInterfaceIterator(device, request, iterHolder); + var ret = IoKitUsb.CreateInterfaceIterator(device, request, iterHolder); if (ret != 0) throwException("internal error (CreateInterfaceIterator)"); @@ -223,13 +245,13 @@ private InterfaceInfo findInterface(int interfaceNumber) { if (intf == null) continue; - cleanup.add(() -> IoKitUSB.Release(intf)); + cleanup.add(() -> IoKitUsb.Release(intf)); - IoKitUSB.GetInterfaceNumber(intf, intfNumberHolder); + IoKitUsb.GetInterfaceNumber(intf, intfNumberHolder); if (intfNumberHolder.get(JAVA_INT, 0) != interfaceNumber) continue; - IoKitUSB.AddRef(intf); + IoKitUsb.AddRef(intf); return new InterfaceInfo(intf, interfaceNumber); } } @@ -245,14 +267,14 @@ public synchronized void claimInterface(int interfaceNumber) { try (var cleanup = new ScopeCleanup()) { - var interfaceInfo = findInterface(interfaceNumber); - cleanup.add(() -> IoKitUSB.Release(interfaceInfo.iokitInterface())); + var interfaceInfo = findInterfaceInfo(interfaceNumber); + cleanup.add(() -> IoKitUsb.Release(interfaceInfo.iokitInterface())); - var ret = IoKitUSB.USBInterfaceOpen(interfaceInfo.iokitInterface()); + var ret = IoKitUsb.USBInterfaceOpen(interfaceInfo.iokitInterface()); if (ret != 0) throwException(ret, "claiming interface failed"); - IoKitUSB.AddRef(interfaceInfo.iokitInterface()); + IoKitUsb.AddRef(interfaceInfo.iokitInterface()); claimedInterfaces.add(interfaceInfo); setClaimed(interfaceNumber, true); addInterfaceEventSource(interfaceInfo); @@ -268,14 +290,10 @@ public synchronized void selectAlternateSetting(int interfaceNumber, int alterna // check alternate setting var altSetting = intf.getAlternate(alternateNumber); - if (altSetting == null) - throwException("interface %d does not have an alternate interface setting %d", interfaceNumber, - alternateNumber); - var intfInfo = claimedInterfaces.stream().filter(interf -> interf.interfaceNumber() == interfaceNumber).findFirst().get(); - var ret = IoKitUSB.SetAlternateInterface(intfInfo.iokitInterface(), (byte) alternateNumber); + var ret = IoKitUsb.SetAlternateInterface(intfInfo.iokitInterface(), (byte) alternateNumber); if (ret != 0) throwException(ret, "setting alternate interface failed"); @@ -292,16 +310,16 @@ public synchronized void releaseInterface(int interfaceNumber) { var interfaceInfo = claimedInterfaces.stream().filter(info -> info.interfaceNumber == interfaceNumber).findFirst().get(); - var source = IoKitUSB.GetInterfaceAsyncEventSource(interfaceInfo.iokitInterface()); + var source = IoKitUsb.GetInterfaceAsyncEventSource(interfaceInfo.iokitInterface()); if (source.address() != 0) asyncTask.removeEventSource(source); - var ret = IoKitUSB.USBInterfaceClose(interfaceInfo.iokitInterface()); + var ret = IoKitUsb.USBInterfaceClose(interfaceInfo.iokitInterface()); if (ret != 0) throwException(ret, "releasing interface failed"); claimedInterfaces.remove(interfaceInfo); - IoKitUSB.Release(interfaceInfo.iokitInterface()); + IoKitUsb.Release(interfaceInfo.iokitInterface()); setClaimed(interfaceNumber, false); updateEndpointList(); @@ -329,14 +347,14 @@ private void updateEndpointList() { var intf = interfaceInfo.iokitInterface(); var numEndpointsHolder = arena.allocate(JAVA_BYTE); - var ret = IoKitUSB.GetNumEndpoints(intf, numEndpointsHolder); + var ret = IoKitUsb.GetNumEndpoints(intf, numEndpointsHolder); if (ret != 0) throwException(ret, "internal error (GetNumEndpoints)"); var numEndpoints = numEndpointsHolder.get(JAVA_BYTE, 0) & 255; for (var pipeIndex = 1; pipeIndex <= numEndpoints; pipeIndex++) { - ret = IoKitUSB.GetPipeProperties(intf, (byte) pipeIndex, directionHolder, numberHolder, + ret = IoKitUsb.GetPipeProperties(intf, (byte) pipeIndex, directionHolder, numberHolder, transferTypeHolder, maxPacketSizeHolder, intervalHolder); if (ret != 0) throwException(ret, "internal error (GetPipeProperties)"); @@ -355,10 +373,10 @@ private void updateEndpointList() { } @SuppressWarnings("SameParameterValue") - private synchronized EndpointInfo getEndpointInfo(int endpointNumber, USBDirection direction, - USBTransferType transferType1, USBTransferType transferType2) { + private synchronized EndpointInfo getEndpointInfo(int endpointNumber, UsbDirection direction, + UsbTransferType transferType1, UsbTransferType transferType2) { if (endpoints != null) { - var endpointAddress = (byte) (endpointNumber | (direction == USBDirection.IN ? 0x80 : 0)); + var endpointAddress = (byte) (endpointNumber | (direction == UsbDirection.IN ? 0x80 : 0)); var endpointInfo = endpoints.get(endpointAddress); if (endpointInfo != null && (endpointInfo.transferType == transferType1 || endpointInfo.transferType == transferType2)) return endpointInfo; @@ -376,32 +394,32 @@ private synchronized EndpointInfo getEndpointInfo(int endpointNumber, USBDirecti throw new AssertionError("not reached"); } - private static MemorySegment createDeviceRequest(Arena arena, USBDirection direction, USBControlTransfer setup, + private static MemorySegment createDeviceRequest(Arena arena, UsbDirection direction, UsbControlTransfer setup, MemorySegment data) { var deviceRequest = IOUSBDevRequest.allocate(arena); var bmRequestType = - (direction == USBDirection.IN ? 0x80 : 0x00) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); - IOUSBDevRequest.bmRequestType$set(deviceRequest, (byte) bmRequestType); - IOUSBDevRequest.bRequest$set(deviceRequest, (byte) setup.request()); - IOUSBDevRequest.wValue$set(deviceRequest, (short) setup.value()); - IOUSBDevRequest.wIndex$set(deviceRequest, (short) setup.index()); - IOUSBDevRequest.wLength$set(deviceRequest, (short) data.byteSize()); - IOUSBDevRequest.pData$set(deviceRequest, data); + (direction == UsbDirection.IN ? 0x80 : 0x00) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); + IOUSBDevRequest.bmRequestType(deviceRequest, (byte) bmRequestType); + IOUSBDevRequest.bRequest(deviceRequest, (byte) setup.request()); + IOUSBDevRequest.wValue(deviceRequest, (short) setup.value()); + IOUSBDevRequest.wIndex(deviceRequest, (short) setup.index()); + IOUSBDevRequest.wLength(deviceRequest, (short) data.byteSize()); + IOUSBDevRequest.pData(deviceRequest, data); return deviceRequest; } @Override - public byte[] controlTransferIn(USBControlTransfer setup, int length) { + public byte @NotNull [] controlTransferIn(@NotNull UsbControlTransfer setup, int length) { try (var arena = Arena.ofConfined()) { var data = arena.allocate(length); - var deviceRequest = createDeviceRequest(arena, USBDirection.IN, setup, data); + var deviceRequest = createDeviceRequest(arena, UsbDirection.IN, setup, data); var transfer = new MacosTransfer(); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); synchronized (transfer) { submitControlTransfer(deviceRequest, transfer); - waitForTransfer(transfer, 0, USBDirection.IN, 0); + waitForTransfer(transfer, 0, UsbDirection.IN, 0); } return data.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); @@ -409,83 +427,85 @@ public byte[] controlTransferIn(USBControlTransfer setup, int length) { } @Override - public void controlTransferOut(USBControlTransfer setup, byte[] data) { + public void controlTransferOut(@NotNull UsbControlTransfer setup, byte[] data) { try (var arena = Arena.ofConfined()) { var dataLength = data != null ? data.length : 0; var dataSegment = arena.allocate(dataLength); if (dataLength > 0) dataSegment.copyFrom(MemorySegment.ofArray(data)); - var deviceRequest = createDeviceRequest(arena, USBDirection.OUT, setup, dataSegment); + var deviceRequest = createDeviceRequest(arena, UsbDirection.OUT, setup, dataSegment); var transfer = new MacosTransfer(); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); synchronized (transfer) { submitControlTransfer(deviceRequest, transfer); - waitForTransfer(transfer, 0, USBDirection.OUT, 0); + waitForTransfer(transfer, 0, UsbDirection.OUT, 0); } } } @Override - public void transferOut(int endpointNumber, byte[] data, int offset, int length, int timeout) { - - var epInfo = getEndpointInfo(endpointNumber, USBDirection.OUT, USBTransferType.BULK, - USBTransferType.INTERRUPT); - - try (var arena = Arena.ofConfined()) { - var nativeData = arena.allocateArray(JAVA_BYTE, length); - nativeData.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); - - var transfer = new MacosTransfer(); - transfer.setData(nativeData); - transfer.setDataSize(length); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); - - synchronized (transfer) { - if (timeout <= 0 || epInfo.transferType() == USBTransferType.BULK) { - // no timeout or timeout handled by operating system - submitTransferOut(endpointNumber, transfer, timeout); - waitForTransfer(transfer, 0, USBDirection.OUT, endpointNumber); - - } else { - // interrupt transfer with timeout - submitTransferOut(endpointNumber, transfer, 0); - waitForTransfer(transfer, timeout, USBDirection.OUT, endpointNumber); - } + public void transferOut(int endpointNumber, byte @NotNull [] data, int offset, int length, int timeout) { + + var epInfo = getEndpointInfo(endpointNumber, UsbDirection.OUT, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); + + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var nativeData = arena.allocate(JAVA_BYTE, length); + nativeData.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); + + var transfer = new MacosTransfer(); + transfer.setData(nativeData); + transfer.setDataSize(length); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); + + synchronized (transfer) { + if (timeout <= 0 || epInfo.transferType() == UsbTransferType.BULK) { + // no timeout or timeout handled by operating system + submitTransferOut(endpointNumber, transfer, timeout); + waitForTransfer(transfer, 0, UsbDirection.OUT, endpointNumber); + + } else { + // interrupt transfer with timeout + submitTransferOut(endpointNumber, transfer, 0); + waitForTransfer(transfer, timeout, UsbDirection.OUT, endpointNumber); } } } @Override - public byte[] transferIn(int endpointNumber, int timeout) { - - var epInfo = getEndpointInfo(endpointNumber, USBDirection.IN, USBTransferType.BULK, - USBTransferType.INTERRUPT); - - try (var arena = Arena.ofConfined()) { - var nativeData = arena.allocateArray(JAVA_BYTE, epInfo.packetSize()); - - var transfer = new MacosTransfer(); - transfer.setData(nativeData); - transfer.setDataSize(epInfo.packetSize()); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); - - synchronized (transfer) { - if (timeout <= 0 || epInfo.transferType() == USBTransferType.BULK) { - // no timeout, or timeout handled by operating system - submitTransferIn(endpointNumber, transfer, timeout); - waitForTransfer(transfer, 0, USBDirection.IN, endpointNumber); - - } else { - // interrupt transfer with timeout - submitTransferIn(endpointNumber, transfer, 0); - waitForTransfer(transfer, timeout, USBDirection.IN, endpointNumber); - } + public byte @NotNull [] transferIn(int endpointNumber, int timeout) { + + var epInfo = getEndpointInfo(endpointNumber, UsbDirection.IN, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); + + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var nativeData = arena.allocate(JAVA_BYTE, epInfo.packetSize()); + + var transfer = new MacosTransfer(); + transfer.setData(nativeData); + transfer.setDataSize(epInfo.packetSize()); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); + + synchronized (transfer) { + if (timeout <= 0 || epInfo.transferType() == UsbTransferType.BULK) { + // no timeout, or timeout handled by operating system + submitTransferIn(endpointNumber, transfer, timeout); + waitForTransfer(transfer, 0, UsbDirection.IN, endpointNumber); + + } else { + // interrupt transfer with timeout + submitTransferIn(endpointNumber, transfer, 0); + waitForTransfer(transfer, timeout, UsbDirection.IN, endpointNumber); } - - return nativeData.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); } + + return nativeData.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); } /** @@ -500,22 +520,24 @@ public byte[] transferIn(int endpointNumber, int timeout) { */ synchronized void submitTransferIn(int endpointNumber, MacosTransfer transfer, int timeout) { - var epInfo = getEndpointInfo(endpointNumber, USBDirection.IN, USBTransferType.BULK, - USBTransferType.INTERRUPT); + var epInfo = getEndpointInfo(endpointNumber, UsbDirection.IN, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); asyncTask.prepareForSubmission(transfer); // submit transfer int ret; if (timeout <= 0) - ret = IoKitUSB.ReadPipeAsync(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), + ret = IoKitUsb.ReadPipeAsync(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), transfer.dataSize(), asyncTask.nativeCompletionCallback(), MemorySegment.ofAddress(transfer.id())); else - ret = IoKitUSB.ReadPipeAsyncTO(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), + ret = IoKitUsb.ReadPipeAsyncTO(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), transfer.dataSize(), timeout, timeout, asyncTask.nativeCompletionCallback(), MemorySegment.ofAddress(transfer.id())); - if (ret != 0) + if (ret != 0) { + asyncTask.submissionFailed(transfer); throwException(ret, "error occurred while reading from endpoint %d", endpointNumber); + } } /** @@ -530,22 +552,24 @@ synchronized void submitTransferIn(int endpointNumber, MacosTransfer transfer, i */ synchronized void submitTransferOut(int endpointNumber, MacosTransfer transfer, int timeout) { - var epInfo = getEndpointInfo(endpointNumber, USBDirection.OUT, USBTransferType.BULK, - USBTransferType.INTERRUPT); + var epInfo = getEndpointInfo(endpointNumber, UsbDirection.OUT, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); asyncTask.prepareForSubmission(transfer); // submit transfer int ret; if (timeout <= 0) - ret = IoKitUSB.WritePipeAsync(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), + ret = IoKitUsb.WritePipeAsync(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), transfer.dataSize(), asyncTask.nativeCompletionCallback(), MemorySegment.ofAddress(transfer.id())); else - ret = IoKitUSB.WritePipeAsyncTO(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), + ret = IoKitUsb.WritePipeAsyncTO(epInfo.iokitInterface(), epInfo.pipeIndex(), transfer.data(), transfer.dataSize(), timeout, timeout, asyncTask.nativeCompletionCallback(), MemorySegment.ofAddress(transfer.id())); - if (ret != 0) + if (ret != 0) { + asyncTask.submissionFailed(transfer); throwException(ret, "error occurred while transmitting to endpoint %d", endpointNumber); + } } /** @@ -560,11 +584,13 @@ synchronized void submitControlTransfer(MemorySegment deviceRequest, MacosTransf asyncTask.prepareForSubmission(transfer); // submit transfer - var ret = IoKitUSB.DeviceRequestAsync(device, deviceRequest, asyncTask.nativeCompletionCallback(), + var ret = IoKitUsb.DeviceRequestAsync(device, deviceRequest, asyncTask.nativeCompletionCallback(), MemorySegment.ofAddress(transfer.id())); - if (ret != 0) + if (ret != 0) { + asyncTask.submissionFailed(transfer); throwException(ret, "control transfer failed"); + } } @Override @@ -573,37 +599,37 @@ protected Transfer createTransfer() { } @Override - public void abortTransfers(USBDirection direction, int endpointNumber) { - var epInfo = getEndpointInfo(endpointNumber, direction, USBTransferType.BULK, - USBTransferType.INTERRUPT); + public synchronized void abortTransfers(UsbDirection direction, int endpointNumber) { + var epInfo = getEndpointInfo(endpointNumber, direction, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); - var ret = IoKitUSB.AbortPipe(epInfo.iokitInterface(), epInfo.pipeIndex()); + var ret = IoKitUsb.AbortPipe(epInfo.iokitInterface(), epInfo.pipeIndex()); if (ret != 0) throwException(ret, "aborting transfers failed"); } @Override - public void clearHalt(USBDirection direction, int endpointNumber) { - var epInfo = getEndpointInfo(endpointNumber, direction, USBTransferType.BULK, - USBTransferType.INTERRUPT); + public synchronized void clearHalt(UsbDirection direction, int endpointNumber) { + var epInfo = getEndpointInfo(endpointNumber, direction, UsbTransferType.BULK, + UsbTransferType.INTERRUPT); - var ret = IoKitUSB.ClearPipeStallBothEnds(epInfo.iokitInterface(), epInfo.pipeIndex()); + var ret = IoKitUsb.ClearPipeStallBothEnds(epInfo.iokitInterface(), epInfo.pipeIndex()); if (ret != 0) throwException(ret, "clearing halt condition failed"); } @Override - public synchronized InputStream openInputStream(int endpointNumber, int bufferSize) { + public synchronized @NotNull InputStream openInputStream(int endpointNumber, int bufferSize) { // check that endpoint number is valid - getEndpointInfo(endpointNumber, USBDirection.IN, USBTransferType.BULK, null); + getEndpointInfo(endpointNumber, UsbDirection.IN, UsbTransferType.BULK, null); return new MacosEndpointInputStream(this, endpointNumber, bufferSize); } @Override - public synchronized OutputStream openOutputStream(int endpointNumber, int bufferSize) { + public synchronized @NotNull OutputStream openOutputStream(int endpointNumber, int bufferSize) { // check that endpoint number is valid - getEndpointInfo(endpointNumber, USBDirection.OUT, USBTransferType.BULK, null); + getEndpointInfo(endpointNumber, UsbDirection.OUT, UsbTransferType.BULK, null); return new MacosEndpointOutputStream(this, endpointNumber, bufferSize); } @@ -613,11 +639,11 @@ protected void throwOSException(int errorCode, String message, Object... args) { throwException(errorCode, message, args); } - private static USBTransferType getTransferType(byte macosTransferType) { + private static UsbTransferType getTransferType(byte macosTransferType) { return switch (macosTransferType) { - case 1 -> USBTransferType.ISOCHRONOUS; - case 2 -> USBTransferType.BULK; - case 3 -> USBTransferType.INTERRUPT; + case 1 -> UsbTransferType.ISOCHRONOUS; + case 2 -> UsbTransferType.BULK; + case 3 -> UsbTransferType.INTERRUPT; default -> null; }; } @@ -625,7 +651,7 @@ private static USBTransferType getTransferType(byte macosTransferType) { private synchronized void addDeviceEventSource() { try (var innerArena = Arena.ofConfined()) { var sourceHolder = innerArena.allocate(ADDRESS); - var ret = IoKitUSB.CreateDeviceAsyncEventSource(device, sourceHolder); + var ret = IoKitUsb.CreateDeviceAsyncEventSource(device, sourceHolder); if (ret != 0) throwException(ret, "internal error (CreateDeviceAsyncEventSource)"); var source = dereference(sourceHolder); @@ -636,7 +662,7 @@ private synchronized void addDeviceEventSource() { private synchronized void addInterfaceEventSource(InterfaceInfo interfaceInfo) { try (var innerArena = Arena.ofConfined()) { var sourceHolder = innerArena.allocate(ADDRESS); - var ret = IoKitUSB.CreateInterfaceAsyncEventSource(interfaceInfo.iokitInterface(), sourceHolder); + var ret = IoKitUsb.CreateInterfaceAsyncEventSource(interfaceInfo.iokitInterface(), sourceHolder); if (ret != 0) throwException(ret, "internal error (CreateInterfaceAsyncEventSource)"); var source = dereference(sourceHolder); @@ -647,6 +673,6 @@ private synchronized void addInterfaceEventSource(InterfaceInfo interfaceInfo) { record InterfaceInfo(MemorySegment iokitInterface, int interfaceNumber) { } - record EndpointInfo(MemorySegment iokitInterface, byte pipeIndex, USBTransferType transferType, int packetSize) { + record EndpointInfo(MemorySegment iokitInterface, byte pipeIndex, UsbTransferType transferType, int packetSize) { } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDeviceRegistry.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDeviceRegistry.java similarity index 82% rename from java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDeviceRegistry.java rename to java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDeviceRegistry.java index d2bb8c0a..b2126246 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDeviceRegistry.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbDeviceRegistry.java @@ -7,32 +7,34 @@ package net.codecrete.usb.macos; -import net.codecrete.usb.USBDevice; +import net.codecrete.usb.UsbDevice; import net.codecrete.usb.common.ScopeCleanup; -import net.codecrete.usb.common.USBDeviceRegistry; +import net.codecrete.usb.common.UsbDeviceRegistry; import net.codecrete.usb.macos.gen.corefoundation.CoreFoundation; import net.codecrete.usb.macos.gen.iokit.IOKit; +import net.codecrete.usb.macos.gen.iokit.IOServiceAddMatchingNotification$callback; -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; import java.util.ArrayList; import java.util.function.Consumer; import static java.lang.System.Logger.Level.INFO; +import static java.lang.System.Logger.Level.WARNING; import static java.lang.foreign.MemorySegment.NULL; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; import static net.codecrete.usb.macos.CoreFoundationHelper.createCFStringRef; -import static net.codecrete.usb.macos.MacosUSBException.throwException; +import static net.codecrete.usb.macos.MacosUsbException.throwException; /** * MacOS implementation of USB device registry. */ @SuppressWarnings("java:S116") -public class MacosUSBDeviceRegistry extends USBDeviceRegistry { +public class MacosUsbDeviceRegistry extends UsbDeviceRegistry { - private static final System.Logger LOG = System.getLogger(MacosUSBDeviceRegistry.class.getName()); + private static final System.Logger LOG = System.getLogger(MacosUsbDeviceRegistry.class.getName()); private static final MemorySegment KEY_ID_VENDOR; private static final MemorySegment KEY_ID_PRODUCT; @@ -74,27 +76,23 @@ protected void monitorDevices() { try { // setup run loop, run loop source and notification port - var notifyPort = IOKit.IONotificationPortCreate(IOKit.kIOMasterPortDefault$get()); + var notifyPort = IOKit.IONotificationPortCreate(IOKit.kIOMasterPortDefault()); var runLoopSource = IOKit.IONotificationPortGetRunLoopSource(notifyPort); var runLoop = CoreFoundation.CFRunLoopGetCurrent(); - CoreFoundation.CFRunLoopAddSource(runLoop, runLoopSource, IOKit.kCFRunLoopDefaultMode$get()); + CoreFoundation.CFRunLoopAddSource(runLoop, runLoopSource, IOKit.kCFRunLoopDefaultMode()); // setup notification for connected devices - var onDeviceConnectedMH = MethodHandles.lookup().findVirtual(MacosUSBDeviceRegistry.class, - "onDevicesConnected", MethodType.methodType(void.class, MemorySegment.class, int.class)); var deviceConnectedIter = setupNotification(arena, notifyPort, IOKit.kIOFirstMatchNotification(), - onDeviceConnectedMH); + this::onDevicesConnected); // iterate current devices in order to arm the notifications (and build initial device list) - var deviceList = new ArrayList(); + var deviceList = new ArrayList(); iterateDevices(deviceConnectedIter, device -> deviceList.add(device)); // NOSONAR setInitialDeviceList(deviceList); // setup notification for disconnected devices - var onDeviceDisconnectedMH = MethodHandles.lookup().findVirtual(MacosUSBDeviceRegistry.class, - "onDevicesDisconnected", MethodType.methodType(void.class, MemorySegment.class, int.class)); var deviceDisconnectedIter = setupNotification(arena, notifyPort, IOKit.kIOTerminatedNotification(), - onDeviceDisconnectedMH); + this::onDevicesDisconnected); // iterate current devices in order to arm the notifications onDevicesDisconnected(NULL, deviceDisconnectedIter); @@ -106,6 +104,7 @@ protected void monitorDevices() { // loop forever CoreFoundation.CFRunLoopRun(); + LOG.log(WARNING, "unexpected end of CFRunLoopRun"); } } @@ -130,7 +129,7 @@ private void iterateDevices(int iterator, IOKitDeviceConsumer consumer) { var device = IoKitHelper.getInterface(service, IoKitHelper.kIOUSBDeviceUserClientTypeID, IoKitHelper.kIOUSBDeviceInterfaceID187); if (device != null) - cleanup.add(() -> IoKitUSB.Release(device)); + cleanup.add(() -> IoKitUsb.Release(device)); // get entry ID (as unique ID) var ret = IOKit.IORegistryEntryGetRegistryEntryID(service, entryIdHolder); @@ -148,7 +147,7 @@ private void iterateDevices(int iterator, IOKitDeviceConsumer consumer) { /** * Calls the consumer for all devices produced by the iterator. *

- * This method tries to create a {@link USBDevice} instance. + * This method tries to create a {@link UsbDevice} instance. * If it fails, an information is printed, but the consumer is not called. *

* @@ -156,7 +155,7 @@ private void iterateDevices(int iterator, IOKitDeviceConsumer consumer) { * @param consumer the consumer */ @SuppressWarnings("java:S106") - private void iterateDevices(int iterator, Consumer consumer) { + private void iterateDevices(int iterator, Consumer consumer) { iterateDevices(iterator, (entryId, service, deviceIntf) -> { var deviceInfo = new VidPid(); @@ -172,7 +171,7 @@ private void iterateDevices(int iterator, Consumer consumer) { }); } - private USBDevice createDevice(Long entryID, int service, MemorySegment deviceIntf, VidPid info) { + private UsbDevice createDevice(Long entryID, int service, MemorySegment deviceIntf, VidPid info) { if (deviceIntf == null) return null; @@ -187,7 +186,7 @@ private USBDevice createDevice(Long entryID, int service, MemorySegment deviceIn info.vid = vendorId; info.pid = productId; - var device = new MacosUSBDevice(deviceIntf, entryID, vendorId, productId); + var device = new MacosUsbDevice(deviceIntf, entryID, vendorId, productId); var manufacturer = IoKitHelper.getPropertyString(service, KEY_VENDOR, arena); var product = IoKitHelper.getPropertyString(service, KEY_PRODUCT, arena); @@ -212,14 +211,13 @@ private USBDevice createDevice(Long entryID, int service, MemorySegment deviceIn } private int setupNotification(Arena arena, MemorySegment notifyPort, MemorySegment notificationType, - MethodHandle callback) { + IOServiceAddMatchingNotification$callback.Function callback) { // new matching dictionary for (dis)connected device notifications (NOSONAR) var matchingDict = IOKit.IOServiceMatching(IOKit.kIOUSBDeviceClassName()); // create callback stub - var onDeviceCallbackStub = Linker.nativeLinker().upcallStub(callback.bindTo(this), - FunctionDescriptor.ofVoid(ADDRESS, JAVA_INT), Arena.global()); + var onDeviceCallbackStub = IOServiceAddMatchingNotification$callback.allocate(callback, Arena.global()); // Set up a notification to be called when a device is first matched / terminated by I/O Kit. // This method consumes the matchingDict reference. @@ -261,19 +259,7 @@ private void onDevicesConnected(MemorySegment ignoredRefCon, int iterator) { private void onDevicesDisconnected(MemorySegment ignoredRefCon, int iterator) { // process device iterator for disconnected devices - iterateDevices(iterator, (entryId, service, deviceIntf) -> { - var device = findDevice(entryId); - if (device == null) - return; - - try { - ((MacosUSBDevice) device).closeFully(); - } catch (Exception e) { - LOG.log(INFO, "failed to close USB device - ignoring exception", e); - } - - removeDevice(entryId); - }); + iterateDevices(iterator, (entryId, _, _) -> closeAndRemoveDevice(entryId)); } @FunctionalInterface diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBException.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbException.java similarity index 77% rename from java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBException.java rename to java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbException.java index 90653942..8731c61f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUsbException.java @@ -6,16 +6,16 @@ // package net.codecrete.usb.macos; -import net.codecrete.usb.USBException; -import net.codecrete.usb.USBStallException; -import net.codecrete.usb.USBTimeoutException; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbStallException; +import net.codecrete.usb.UsbTimeoutException; import net.codecrete.usb.macos.gen.iokit.IOKit; import net.codecrete.usb.macos.gen.mach.mach; /** * Exception thrown if a macOS specific error occurs. */ -public class MacosUSBException extends USBException { +public class MacosUsbException extends UsbException { /** * Creates a new instance. @@ -26,13 +26,13 @@ public class MacosUSBException extends USBException { * @param message exception message * @param errorCode macOS error code (usually returned by macOS functions) */ - public MacosUSBException(String message, int errorCode) { + public MacosUsbException(String message, int errorCode) { super(String.format("%s: %s", message, machErrorMessage(errorCode)), errorCode); } private static String machErrorMessage(int errorCode) { var msg = mach.mach_error_string(errorCode); - return msg.getUtf8String(0); + return msg.getString(0); } /** @@ -48,11 +48,11 @@ private static String machErrorMessage(int errorCode) { static void throwException(int errorCode, String message, Object... args) { var formattedMessage = String.format(message, args); if (errorCode == IOKit.kIOUSBPipeStalled()) { - throw new USBStallException(formattedMessage); + throw new UsbStallException(formattedMessage); } else if (errorCode == IOKit.kIOUSBTransactionTimeout()) { - throw new USBTimeoutException(formattedMessage); + throw new UsbTimeoutException(formattedMessage); } else { - throw new MacosUSBException(formattedMessage, errorCode); + throw new MacosUsbException(formattedMessage, errorCode); } } @@ -63,7 +63,7 @@ static void throwException(int errorCode, String message, Object... args) { * @param args arguments for exception message */ static void throwException(String message, Object... args) { - throw new USBException(String.format(message, args)); + throw new UsbException(String.format(message, args)); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFMessagePortCreateLocal$callout.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFMessagePortCreateLocal$callout.java new file mode 100644 index 00000000..760f9200 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFMessagePortCreateLocal$callout.java @@ -0,0 +1,73 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.corefoundation; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +/** + * {@snippet lang=c : + * CFMessagePortCallBack callout + * } + */ +public final class CFMessagePortCreateLocal$callout { + + private CFMessagePortCreateLocal$callout() { + // Should not be called directly + } + + /** + * The function pointer signature, expressed as a functional interface + */ + public interface Function { + MemorySegment apply(MemorySegment _x0, int _x1, MemorySegment _x2, MemorySegment _x3); + } + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_INT, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + private static final MethodHandle UP$MH = CoreFoundation.upcallHandle(CFMessagePortCreateLocal$callout.Function.class, "apply", $DESC); + + /** + * Allocates a new upcall stub, whose implementation is defined by {@code fi}. + * The lifetime of the returned segment is managed by {@code arena} + */ + public static MemorySegment allocate(CFMessagePortCreateLocal$callout.Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, arena); + } + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static MemorySegment invoke(MemorySegment funcPtr, MemorySegment _x0, int _x1, MemorySegment _x2, MemorySegment _x3) { + try { + return (MemorySegment) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFRange.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFRange.java index f0f8887b..52df333e 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFRange.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFRange.java @@ -2,84 +2,172 @@ package net.codecrete.usb.macos.gen.corefoundation; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct { * CFIndex location; * CFIndex length; - * }; + * } * } */ public class CFRange { - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; + CFRange() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + CoreFoundation.C_LONG.withName("location"), + CoreFoundation.C_LONG.withName("length") + ).withName("CFRange"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; + } + + private static final OfLong location$LAYOUT = (OfLong)$LAYOUT.select(groupElement("location")); + + /** + * Layout for field: + * {@snippet lang=c : + * CFIndex location + * } + */ + public static final OfLong location$layout() { + return location$LAYOUT; } - public static VarHandle location$VH() { - return constants$0.const$1; + + private static final long location$OFFSET = $LAYOUT.byteOffset(groupElement("location")); + + /** + * Offset for field: + * {@snippet lang=c : + * CFIndex location + * } + */ + public static final long location$offset() { + return location$OFFSET; } + /** * Getter for field: - * {@snippet : - * CFIndex location; + * {@snippet lang=c : + * CFIndex location * } */ - public static long location$get(MemorySegment seg) { - return (long)constants$0.const$1.get(seg); + public static long location(MemorySegment struct) { + return struct.get(location$LAYOUT, location$OFFSET); } + /** * Setter for field: - * {@snippet : - * CFIndex location; + * {@snippet lang=c : + * CFIndex location * } */ - public static void location$set(MemorySegment seg, long x) { - constants$0.const$1.set(seg, x); + public static void location(MemorySegment struct, long fieldValue) { + struct.set(location$LAYOUT, location$OFFSET, fieldValue); } - public static long location$get(MemorySegment seg, long index) { - return (long)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void location$set(MemorySegment seg, long index, long x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfLong length$LAYOUT = (OfLong)$LAYOUT.select(groupElement("length")); + + /** + * Layout for field: + * {@snippet lang=c : + * CFIndex length + * } + */ + public static final OfLong length$layout() { + return length$LAYOUT; } - public static VarHandle length$VH() { - return constants$0.const$2; + + private static final long length$OFFSET = $LAYOUT.byteOffset(groupElement("length")); + + /** + * Offset for field: + * {@snippet lang=c : + * CFIndex length + * } + */ + public static final long length$offset() { + return length$OFFSET; } + /** * Getter for field: - * {@snippet : - * CFIndex length; + * {@snippet lang=c : + * CFIndex length * } */ - public static long length$get(MemorySegment seg) { - return (long)constants$0.const$2.get(seg); + public static long length(MemorySegment struct) { + return struct.get(length$LAYOUT, length$OFFSET); } + /** * Setter for field: - * {@snippet : - * CFIndex length; + * {@snippet lang=c : + * CFIndex length * } */ - public static void length$set(MemorySegment seg, long x) { - constants$0.const$2.set(seg, x); + public static void length(MemorySegment struct, long fieldValue) { + struct.set(length$LAYOUT, length$OFFSET, fieldValue); } - public static long length$get(MemorySegment seg, long index) { - return (long)constants$0.const$2.get(seg.asSlice(index*sizeof())); + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static void length$set(MemorySegment seg, long index, long x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFUUIDBytes.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFUUIDBytes.java index 26940ac9..5b52339e 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFUUIDBytes.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CFUUIDBytes.java @@ -2,13 +2,18 @@ package net.codecrete.usb.macos.gen.corefoundation; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct { * UInt8 byte0; * UInt8 byte1; @@ -26,452 +31,787 @@ * UInt8 byte13; * UInt8 byte14; * UInt8 byte15; - * }; + * } * } */ public class CFUUIDBytes { - public static MemoryLayout $LAYOUT() { - return constants$3.const$3; + CFUUIDBytes() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + CoreFoundation.C_CHAR.withName("byte0"), + CoreFoundation.C_CHAR.withName("byte1"), + CoreFoundation.C_CHAR.withName("byte2"), + CoreFoundation.C_CHAR.withName("byte3"), + CoreFoundation.C_CHAR.withName("byte4"), + CoreFoundation.C_CHAR.withName("byte5"), + CoreFoundation.C_CHAR.withName("byte6"), + CoreFoundation.C_CHAR.withName("byte7"), + CoreFoundation.C_CHAR.withName("byte8"), + CoreFoundation.C_CHAR.withName("byte9"), + CoreFoundation.C_CHAR.withName("byte10"), + CoreFoundation.C_CHAR.withName("byte11"), + CoreFoundation.C_CHAR.withName("byte12"), + CoreFoundation.C_CHAR.withName("byte13"), + CoreFoundation.C_CHAR.withName("byte14"), + CoreFoundation.C_CHAR.withName("byte15") + ).withName("CFUUIDBytes"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } - public static VarHandle byte0$VH() { - return constants$3.const$4; + + private static final OfByte byte0$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte0")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static final OfByte byte0$layout() { + return byte0$LAYOUT; + } + + private static final long byte0$OFFSET = $LAYOUT.byteOffset(groupElement("byte0")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static final long byte0$offset() { + return byte0$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte0; + * {@snippet lang=c : + * UInt8 byte0 * } */ - public static byte byte0$get(MemorySegment seg) { - return (byte)constants$3.const$4.get(seg); + public static byte byte0(MemorySegment struct) { + return struct.get(byte0$LAYOUT, byte0$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte0; + * {@snippet lang=c : + * UInt8 byte0 * } */ - public static void byte0$set(MemorySegment seg, byte x) { - constants$3.const$4.set(seg, x); + public static void byte0(MemorySegment struct, byte fieldValue) { + struct.set(byte0$LAYOUT, byte0$OFFSET, fieldValue); } - public static byte byte0$get(MemorySegment seg, long index) { - return (byte)constants$3.const$4.get(seg.asSlice(index*sizeof())); - } - public static void byte0$set(MemorySegment seg, long index, byte x) { - constants$3.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte1$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte1")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static final OfByte byte1$layout() { + return byte1$LAYOUT; } - public static VarHandle byte1$VH() { - return constants$3.const$5; + + private static final long byte1$OFFSET = $LAYOUT.byteOffset(groupElement("byte1")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static final long byte1$offset() { + return byte1$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte1; + * {@snippet lang=c : + * UInt8 byte1 * } */ - public static byte byte1$get(MemorySegment seg) { - return (byte)constants$3.const$5.get(seg); + public static byte byte1(MemorySegment struct) { + return struct.get(byte1$LAYOUT, byte1$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte1; + * {@snippet lang=c : + * UInt8 byte1 * } */ - public static void byte1$set(MemorySegment seg, byte x) { - constants$3.const$5.set(seg, x); + public static void byte1(MemorySegment struct, byte fieldValue) { + struct.set(byte1$LAYOUT, byte1$OFFSET, fieldValue); } - public static byte byte1$get(MemorySegment seg, long index) { - return (byte)constants$3.const$5.get(seg.asSlice(index*sizeof())); - } - public static void byte1$set(MemorySegment seg, long index, byte x) { - constants$3.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte2$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte2")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static final OfByte byte2$layout() { + return byte2$LAYOUT; } - public static VarHandle byte2$VH() { - return constants$4.const$0; + + private static final long byte2$OFFSET = $LAYOUT.byteOffset(groupElement("byte2")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static final long byte2$offset() { + return byte2$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte2; + * {@snippet lang=c : + * UInt8 byte2 * } */ - public static byte byte2$get(MemorySegment seg) { - return (byte)constants$4.const$0.get(seg); + public static byte byte2(MemorySegment struct) { + return struct.get(byte2$LAYOUT, byte2$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte2; + * {@snippet lang=c : + * UInt8 byte2 * } */ - public static void byte2$set(MemorySegment seg, byte x) { - constants$4.const$0.set(seg, x); + public static void byte2(MemorySegment struct, byte fieldValue) { + struct.set(byte2$LAYOUT, byte2$OFFSET, fieldValue); } - public static byte byte2$get(MemorySegment seg, long index) { - return (byte)constants$4.const$0.get(seg.asSlice(index*sizeof())); - } - public static void byte2$set(MemorySegment seg, long index, byte x) { - constants$4.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte3$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte3")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static final OfByte byte3$layout() { + return byte3$LAYOUT; } - public static VarHandle byte3$VH() { - return constants$4.const$1; + + private static final long byte3$OFFSET = $LAYOUT.byteOffset(groupElement("byte3")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static final long byte3$offset() { + return byte3$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte3; + * {@snippet lang=c : + * UInt8 byte3 * } */ - public static byte byte3$get(MemorySegment seg) { - return (byte)constants$4.const$1.get(seg); + public static byte byte3(MemorySegment struct) { + return struct.get(byte3$LAYOUT, byte3$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte3; + * {@snippet lang=c : + * UInt8 byte3 * } */ - public static void byte3$set(MemorySegment seg, byte x) { - constants$4.const$1.set(seg, x); + public static void byte3(MemorySegment struct, byte fieldValue) { + struct.set(byte3$LAYOUT, byte3$OFFSET, fieldValue); } - public static byte byte3$get(MemorySegment seg, long index) { - return (byte)constants$4.const$1.get(seg.asSlice(index*sizeof())); - } - public static void byte3$set(MemorySegment seg, long index, byte x) { - constants$4.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte4$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte4")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static final OfByte byte4$layout() { + return byte4$LAYOUT; } - public static VarHandle byte4$VH() { - return constants$4.const$2; + + private static final long byte4$OFFSET = $LAYOUT.byteOffset(groupElement("byte4")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static final long byte4$offset() { + return byte4$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte4; + * {@snippet lang=c : + * UInt8 byte4 * } */ - public static byte byte4$get(MemorySegment seg) { - return (byte)constants$4.const$2.get(seg); + public static byte byte4(MemorySegment struct) { + return struct.get(byte4$LAYOUT, byte4$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte4; + * {@snippet lang=c : + * UInt8 byte4 * } */ - public static void byte4$set(MemorySegment seg, byte x) { - constants$4.const$2.set(seg, x); - } - public static byte byte4$get(MemorySegment seg, long index) { - return (byte)constants$4.const$2.get(seg.asSlice(index*sizeof())); + public static void byte4(MemorySegment struct, byte fieldValue) { + struct.set(byte4$LAYOUT, byte4$OFFSET, fieldValue); } - public static void byte4$set(MemorySegment seg, long index, byte x) { - constants$4.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte5$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte5")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static final OfByte byte5$layout() { + return byte5$LAYOUT; } - public static VarHandle byte5$VH() { - return constants$4.const$3; + + private static final long byte5$OFFSET = $LAYOUT.byteOffset(groupElement("byte5")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static final long byte5$offset() { + return byte5$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte5; + * {@snippet lang=c : + * UInt8 byte5 * } */ - public static byte byte5$get(MemorySegment seg) { - return (byte)constants$4.const$3.get(seg); + public static byte byte5(MemorySegment struct) { + return struct.get(byte5$LAYOUT, byte5$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte5; + * {@snippet lang=c : + * UInt8 byte5 * } */ - public static void byte5$set(MemorySegment seg, byte x) { - constants$4.const$3.set(seg, x); - } - public static byte byte5$get(MemorySegment seg, long index) { - return (byte)constants$4.const$3.get(seg.asSlice(index*sizeof())); + public static void byte5(MemorySegment struct, byte fieldValue) { + struct.set(byte5$LAYOUT, byte5$OFFSET, fieldValue); } - public static void byte5$set(MemorySegment seg, long index, byte x) { - constants$4.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte6$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte6")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static final OfByte byte6$layout() { + return byte6$LAYOUT; } - public static VarHandle byte6$VH() { - return constants$4.const$4; + + private static final long byte6$OFFSET = $LAYOUT.byteOffset(groupElement("byte6")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static final long byte6$offset() { + return byte6$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte6; + * {@snippet lang=c : + * UInt8 byte6 * } */ - public static byte byte6$get(MemorySegment seg) { - return (byte)constants$4.const$4.get(seg); + public static byte byte6(MemorySegment struct) { + return struct.get(byte6$LAYOUT, byte6$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte6; + * {@snippet lang=c : + * UInt8 byte6 * } */ - public static void byte6$set(MemorySegment seg, byte x) { - constants$4.const$4.set(seg, x); - } - public static byte byte6$get(MemorySegment seg, long index) { - return (byte)constants$4.const$4.get(seg.asSlice(index*sizeof())); + public static void byte6(MemorySegment struct, byte fieldValue) { + struct.set(byte6$LAYOUT, byte6$OFFSET, fieldValue); } - public static void byte6$set(MemorySegment seg, long index, byte x) { - constants$4.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte7$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte7")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static final OfByte byte7$layout() { + return byte7$LAYOUT; } - public static VarHandle byte7$VH() { - return constants$4.const$5; + + private static final long byte7$OFFSET = $LAYOUT.byteOffset(groupElement("byte7")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static final long byte7$offset() { + return byte7$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte7; + * {@snippet lang=c : + * UInt8 byte7 * } */ - public static byte byte7$get(MemorySegment seg) { - return (byte)constants$4.const$5.get(seg); + public static byte byte7(MemorySegment struct) { + return struct.get(byte7$LAYOUT, byte7$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte7; + * {@snippet lang=c : + * UInt8 byte7 * } */ - public static void byte7$set(MemorySegment seg, byte x) { - constants$4.const$5.set(seg, x); + public static void byte7(MemorySegment struct, byte fieldValue) { + struct.set(byte7$LAYOUT, byte7$OFFSET, fieldValue); } - public static byte byte7$get(MemorySegment seg, long index) { - return (byte)constants$4.const$5.get(seg.asSlice(index*sizeof())); - } - public static void byte7$set(MemorySegment seg, long index, byte x) { - constants$4.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte8$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte8")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static final OfByte byte8$layout() { + return byte8$LAYOUT; } - public static VarHandle byte8$VH() { - return constants$5.const$0; + + private static final long byte8$OFFSET = $LAYOUT.byteOffset(groupElement("byte8")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static final long byte8$offset() { + return byte8$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte8; + * {@snippet lang=c : + * UInt8 byte8 * } */ - public static byte byte8$get(MemorySegment seg) { - return (byte)constants$5.const$0.get(seg); + public static byte byte8(MemorySegment struct) { + return struct.get(byte8$LAYOUT, byte8$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte8; + * {@snippet lang=c : + * UInt8 byte8 * } */ - public static void byte8$set(MemorySegment seg, byte x) { - constants$5.const$0.set(seg, x); + public static void byte8(MemorySegment struct, byte fieldValue) { + struct.set(byte8$LAYOUT, byte8$OFFSET, fieldValue); } - public static byte byte8$get(MemorySegment seg, long index) { - return (byte)constants$5.const$0.get(seg.asSlice(index*sizeof())); - } - public static void byte8$set(MemorySegment seg, long index, byte x) { - constants$5.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte9$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte9")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static final OfByte byte9$layout() { + return byte9$LAYOUT; } - public static VarHandle byte9$VH() { - return constants$5.const$1; + + private static final long byte9$OFFSET = $LAYOUT.byteOffset(groupElement("byte9")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static final long byte9$offset() { + return byte9$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte9; + * {@snippet lang=c : + * UInt8 byte9 * } */ - public static byte byte9$get(MemorySegment seg) { - return (byte)constants$5.const$1.get(seg); + public static byte byte9(MemorySegment struct) { + return struct.get(byte9$LAYOUT, byte9$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte9; + * {@snippet lang=c : + * UInt8 byte9 * } */ - public static void byte9$set(MemorySegment seg, byte x) { - constants$5.const$1.set(seg, x); + public static void byte9(MemorySegment struct, byte fieldValue) { + struct.set(byte9$LAYOUT, byte9$OFFSET, fieldValue); } - public static byte byte9$get(MemorySegment seg, long index) { - return (byte)constants$5.const$1.get(seg.asSlice(index*sizeof())); - } - public static void byte9$set(MemorySegment seg, long index, byte x) { - constants$5.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte10$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte10")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static final OfByte byte10$layout() { + return byte10$LAYOUT; } - public static VarHandle byte10$VH() { - return constants$5.const$2; + + private static final long byte10$OFFSET = $LAYOUT.byteOffset(groupElement("byte10")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static final long byte10$offset() { + return byte10$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte10; + * {@snippet lang=c : + * UInt8 byte10 * } */ - public static byte byte10$get(MemorySegment seg) { - return (byte)constants$5.const$2.get(seg); + public static byte byte10(MemorySegment struct) { + return struct.get(byte10$LAYOUT, byte10$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte10; + * {@snippet lang=c : + * UInt8 byte10 * } */ - public static void byte10$set(MemorySegment seg, byte x) { - constants$5.const$2.set(seg, x); + public static void byte10(MemorySegment struct, byte fieldValue) { + struct.set(byte10$LAYOUT, byte10$OFFSET, fieldValue); } - public static byte byte10$get(MemorySegment seg, long index) { - return (byte)constants$5.const$2.get(seg.asSlice(index*sizeof())); - } - public static void byte10$set(MemorySegment seg, long index, byte x) { - constants$5.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte11$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte11")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static final OfByte byte11$layout() { + return byte11$LAYOUT; } - public static VarHandle byte11$VH() { - return constants$5.const$3; + + private static final long byte11$OFFSET = $LAYOUT.byteOffset(groupElement("byte11")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static final long byte11$offset() { + return byte11$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte11; + * {@snippet lang=c : + * UInt8 byte11 * } */ - public static byte byte11$get(MemorySegment seg) { - return (byte)constants$5.const$3.get(seg); + public static byte byte11(MemorySegment struct) { + return struct.get(byte11$LAYOUT, byte11$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte11; + * {@snippet lang=c : + * UInt8 byte11 * } */ - public static void byte11$set(MemorySegment seg, byte x) { - constants$5.const$3.set(seg, x); + public static void byte11(MemorySegment struct, byte fieldValue) { + struct.set(byte11$LAYOUT, byte11$OFFSET, fieldValue); } - public static byte byte11$get(MemorySegment seg, long index) { - return (byte)constants$5.const$3.get(seg.asSlice(index*sizeof())); - } - public static void byte11$set(MemorySegment seg, long index, byte x) { - constants$5.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte12$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte12")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static final OfByte byte12$layout() { + return byte12$LAYOUT; } - public static VarHandle byte12$VH() { - return constants$5.const$4; + + private static final long byte12$OFFSET = $LAYOUT.byteOffset(groupElement("byte12")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static final long byte12$offset() { + return byte12$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte12; + * {@snippet lang=c : + * UInt8 byte12 * } */ - public static byte byte12$get(MemorySegment seg) { - return (byte)constants$5.const$4.get(seg); + public static byte byte12(MemorySegment struct) { + return struct.get(byte12$LAYOUT, byte12$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte12; + * {@snippet lang=c : + * UInt8 byte12 * } */ - public static void byte12$set(MemorySegment seg, byte x) { - constants$5.const$4.set(seg, x); - } - public static byte byte12$get(MemorySegment seg, long index) { - return (byte)constants$5.const$4.get(seg.asSlice(index*sizeof())); + public static void byte12(MemorySegment struct, byte fieldValue) { + struct.set(byte12$LAYOUT, byte12$OFFSET, fieldValue); } - public static void byte12$set(MemorySegment seg, long index, byte x) { - constants$5.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte13$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte13")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static final OfByte byte13$layout() { + return byte13$LAYOUT; } - public static VarHandle byte13$VH() { - return constants$5.const$5; + + private static final long byte13$OFFSET = $LAYOUT.byteOffset(groupElement("byte13")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static final long byte13$offset() { + return byte13$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte13; + * {@snippet lang=c : + * UInt8 byte13 * } */ - public static byte byte13$get(MemorySegment seg) { - return (byte)constants$5.const$5.get(seg); + public static byte byte13(MemorySegment struct) { + return struct.get(byte13$LAYOUT, byte13$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte13; + * {@snippet lang=c : + * UInt8 byte13 * } */ - public static void byte13$set(MemorySegment seg, byte x) { - constants$5.const$5.set(seg, x); + public static void byte13(MemorySegment struct, byte fieldValue) { + struct.set(byte13$LAYOUT, byte13$OFFSET, fieldValue); } - public static byte byte13$get(MemorySegment seg, long index) { - return (byte)constants$5.const$5.get(seg.asSlice(index*sizeof())); - } - public static void byte13$set(MemorySegment seg, long index, byte x) { - constants$5.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte14$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte14")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static final OfByte byte14$layout() { + return byte14$LAYOUT; } - public static VarHandle byte14$VH() { - return constants$6.const$0; + + private static final long byte14$OFFSET = $LAYOUT.byteOffset(groupElement("byte14")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static final long byte14$offset() { + return byte14$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte14; + * {@snippet lang=c : + * UInt8 byte14 * } */ - public static byte byte14$get(MemorySegment seg) { - return (byte)constants$6.const$0.get(seg); + public static byte byte14(MemorySegment struct) { + return struct.get(byte14$LAYOUT, byte14$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte14; + * {@snippet lang=c : + * UInt8 byte14 * } */ - public static void byte14$set(MemorySegment seg, byte x) { - constants$6.const$0.set(seg, x); + public static void byte14(MemorySegment struct, byte fieldValue) { + struct.set(byte14$LAYOUT, byte14$OFFSET, fieldValue); } - public static byte byte14$get(MemorySegment seg, long index) { - return (byte)constants$6.const$0.get(seg.asSlice(index*sizeof())); - } - public static void byte14$set(MemorySegment seg, long index, byte x) { - constants$6.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte byte15$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte15")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static final OfByte byte15$layout() { + return byte15$LAYOUT; } - public static VarHandle byte15$VH() { - return constants$6.const$1; + + private static final long byte15$OFFSET = $LAYOUT.byteOffset(groupElement("byte15")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static final long byte15$offset() { + return byte15$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 byte15; + * {@snippet lang=c : + * UInt8 byte15 * } */ - public static byte byte15$get(MemorySegment seg) { - return (byte)constants$6.const$1.get(seg); + public static byte byte15(MemorySegment struct) { + return struct.get(byte15$LAYOUT, byte15$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 byte15; + * {@snippet lang=c : + * UInt8 byte15 * } */ - public static void byte15$set(MemorySegment seg, byte x) { - constants$6.const$1.set(seg, x); + public static void byte15(MemorySegment struct, byte fieldValue) { + struct.set(byte15$LAYOUT, byte15$OFFSET, fieldValue); } - public static byte byte15$get(MemorySegment seg, long index) { - return (byte)constants$6.const$1.get(seg.asSlice(index*sizeof())); + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static void byte15$set(MemorySegment seg, long index, byte x) { - constants$6.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation$shared.java new file mode 100644 index 00000000..1994933a --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.corefoundation; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class CoreFoundation$shared { + + CoreFoundation$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation.java index 3b1c3e58..a1690ca3 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/CoreFoundation.java @@ -2,254 +2,1249 @@ package net.codecrete.usb.macos.gen.corefoundation; -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class CoreFoundation { +import static java.lang.foreign.MemoryLayout.PathElement.*; - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle CFGetTypeID$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$4,"CFGetTypeID"); +public class CoreFoundation extends CoreFoundation$shared { + + CoreFoundation() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.libraryLookup("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + + + private static class CFGetTypeID { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_LONG, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFGetTypeID"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFTypeID CFGetTypeID(CFTypeRef cf) + * } + */ + public static FunctionDescriptor CFGetTypeID$descriptor() { + return CFGetTypeID.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFTypeID CFGetTypeID(CFTypeRef cf) + * } + */ + public static MethodHandle CFGetTypeID$handle() { + return CFGetTypeID.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFTypeID CFGetTypeID(CFTypeRef cf) + * } + */ + public static MemorySegment CFGetTypeID$address() { + return CFGetTypeID.ADDR; } + /** - * {@snippet : - * CFTypeID CFGetTypeID(CFTypeRef cf); + * {@snippet lang=c : + * extern CFTypeID CFGetTypeID(CFTypeRef cf) * } */ public static long CFGetTypeID(MemorySegment cf) { - var mh$ = CFGetTypeID$MH(); + var mh$ = CFGetTypeID.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFGetTypeID", cf); + } return (long)mh$.invokeExact(cf); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFRelease$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$6,"CFRelease"); + + private static class CFRelease { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFRelease"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * void CFRelease(CFTypeRef cf); + * Function descriptor for: + * {@snippet lang=c : + * extern void CFRelease(CFTypeRef cf) + * } + */ + public static FunctionDescriptor CFRelease$descriptor() { + return CFRelease.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern void CFRelease(CFTypeRef cf) + * } + */ + public static MethodHandle CFRelease$handle() { + return CFRelease.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern void CFRelease(CFTypeRef cf) + * } + */ + public static MemorySegment CFRelease$address() { + return CFRelease.ADDR; + } + + /** + * {@snippet lang=c : + * extern void CFRelease(CFTypeRef cf) * } */ public static void CFRelease(MemorySegment cf) { - var mh$ = CFRelease$MH(); + var mh$ = CFRelease.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFRelease", cf); + } mh$.invokeExact(cf); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFStringGetTypeID$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$1,"CFStringGetTypeID"); + + private static class CFDataCreate { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_LONG + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFDataCreate"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * CFTypeID CFStringGetTypeID(); + * Function descriptor for: + * {@snippet lang=c : + * extern CFDataRef CFDataCreate(CFAllocatorRef allocator, const UInt8 *bytes, CFIndex length) + * } + */ + public static FunctionDescriptor CFDataCreate$descriptor() { + return CFDataCreate.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFDataRef CFDataCreate(CFAllocatorRef allocator, const UInt8 *bytes, CFIndex length) + * } + */ + public static MethodHandle CFDataCreate$handle() { + return CFDataCreate.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFDataRef CFDataCreate(CFAllocatorRef allocator, const UInt8 *bytes, CFIndex length) + * } + */ + public static MemorySegment CFDataCreate$address() { + return CFDataCreate.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFDataRef CFDataCreate(CFAllocatorRef allocator, const UInt8 *bytes, CFIndex length) + * } + */ + public static MemorySegment CFDataCreate(MemorySegment allocator, MemorySegment bytes, long length) { + var mh$ = CFDataCreate.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFDataCreate", allocator, bytes, length); + } + return (MemorySegment)mh$.invokeExact(allocator, bytes, length); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static class CFDataGetBytePtr { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFDataGetBytePtr"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern const UInt8 *CFDataGetBytePtr(CFDataRef theData) + * } + */ + public static FunctionDescriptor CFDataGetBytePtr$descriptor() { + return CFDataGetBytePtr.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern const UInt8 *CFDataGetBytePtr(CFDataRef theData) + * } + */ + public static MethodHandle CFDataGetBytePtr$handle() { + return CFDataGetBytePtr.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern const UInt8 *CFDataGetBytePtr(CFDataRef theData) + * } + */ + public static MemorySegment CFDataGetBytePtr$address() { + return CFDataGetBytePtr.ADDR; + } + + /** + * {@snippet lang=c : + * extern const UInt8 *CFDataGetBytePtr(CFDataRef theData) + * } + */ + public static MemorySegment CFDataGetBytePtr(MemorySegment theData) { + var mh$ = CFDataGetBytePtr.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFDataGetBytePtr", theData); + } + return (MemorySegment)mh$.invokeExact(theData); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static class CFStringGetTypeID { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_LONG ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFStringGetTypeID"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFTypeID CFStringGetTypeID(void) + * } + */ + public static FunctionDescriptor CFStringGetTypeID$descriptor() { + return CFStringGetTypeID.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFTypeID CFStringGetTypeID(void) + * } + */ + public static MethodHandle CFStringGetTypeID$handle() { + return CFStringGetTypeID.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFTypeID CFStringGetTypeID(void) + * } + */ + public static MemorySegment CFStringGetTypeID$address() { + return CFStringGetTypeID.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFTypeID CFStringGetTypeID(void) * } */ public static long CFStringGetTypeID() { - var mh$ = CFStringGetTypeID$MH(); + var mh$ = CFStringGetTypeID.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFStringGetTypeID"); + } return (long)mh$.invokeExact(); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFStringCreateWithCharacters$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$3,"CFStringCreateWithCharacters"); + + private static class CFStringCreateWithCharacters { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_LONG + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFStringCreateWithCharacters"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * CFStringRef CFStringCreateWithCharacters(CFAllocatorRef alloc, const UniChar* chars, CFIndex numChars); + * Function descriptor for: + * {@snippet lang=c : + * extern CFStringRef CFStringCreateWithCharacters(CFAllocatorRef alloc, const UniChar *chars, CFIndex numChars) + * } + */ + public static FunctionDescriptor CFStringCreateWithCharacters$descriptor() { + return CFStringCreateWithCharacters.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFStringRef CFStringCreateWithCharacters(CFAllocatorRef alloc, const UniChar *chars, CFIndex numChars) + * } + */ + public static MethodHandle CFStringCreateWithCharacters$handle() { + return CFStringCreateWithCharacters.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFStringRef CFStringCreateWithCharacters(CFAllocatorRef alloc, const UniChar *chars, CFIndex numChars) + * } + */ + public static MemorySegment CFStringCreateWithCharacters$address() { + return CFStringCreateWithCharacters.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFStringRef CFStringCreateWithCharacters(CFAllocatorRef alloc, const UniChar *chars, CFIndex numChars) * } */ public static MemorySegment CFStringCreateWithCharacters(MemorySegment alloc, MemorySegment chars, long numChars) { - var mh$ = CFStringCreateWithCharacters$MH(); + var mh$ = CFStringCreateWithCharacters.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(alloc, chars, numChars); + if (TRACE_DOWNCALLS) { + traceDowncall("CFStringCreateWithCharacters", alloc, chars, numChars); + } + return (MemorySegment)mh$.invokeExact(alloc, chars, numChars); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFStringGetLength$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$4,"CFStringGetLength"); + + private static class CFStringGetLength { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_LONG, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFStringGetLength"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFIndex CFStringGetLength(CFStringRef theString) + * } + */ + public static FunctionDescriptor CFStringGetLength$descriptor() { + return CFStringGetLength.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFIndex CFStringGetLength(CFStringRef theString) + * } + */ + public static MethodHandle CFStringGetLength$handle() { + return CFStringGetLength.HANDLE; } + /** - * {@snippet : - * CFIndex CFStringGetLength(CFStringRef theString); + * Address for: + * {@snippet lang=c : + * extern CFIndex CFStringGetLength(CFStringRef theString) + * } + */ + public static MemorySegment CFStringGetLength$address() { + return CFStringGetLength.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFIndex CFStringGetLength(CFStringRef theString) * } */ public static long CFStringGetLength(MemorySegment theString) { - var mh$ = CFStringGetLength$MH(); + var mh$ = CFStringGetLength.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFStringGetLength", theString); + } return (long)mh$.invokeExact(theString); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFStringGetCharacters$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$6,"CFStringGetCharacters"); + + private static class CFStringGetCharacters { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + CoreFoundation.C_POINTER, + CFRange.layout(), + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFStringGetCharacters"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern void CFStringGetCharacters(CFStringRef theString, CFRange range, UniChar *buffer) + * } + */ + public static FunctionDescriptor CFStringGetCharacters$descriptor() { + return CFStringGetCharacters.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern void CFStringGetCharacters(CFStringRef theString, CFRange range, UniChar *buffer) + * } + */ + public static MethodHandle CFStringGetCharacters$handle() { + return CFStringGetCharacters.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern void CFStringGetCharacters(CFStringRef theString, CFRange range, UniChar *buffer) + * } + */ + public static MemorySegment CFStringGetCharacters$address() { + return CFStringGetCharacters.ADDR; } + /** - * {@snippet : - * void CFStringGetCharacters(CFStringRef theString, CFRange range, UniChar* buffer); + * {@snippet lang=c : + * extern void CFStringGetCharacters(CFStringRef theString, CFRange range, UniChar *buffer) * } */ public static void CFStringGetCharacters(MemorySegment theString, MemorySegment range, MemorySegment buffer) { - var mh$ = CFStringGetCharacters$MH(); + var mh$ = CFStringGetCharacters.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFStringGetCharacters", theString, range, buffer); + } mh$.invokeExact(theString, range, buffer); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } + private static final int kCFNumberSInt32Type = (int)3L; /** - * {@snippet : - * enum .kCFNumberSInt32Type = 3; + * {@snippet lang=c : + * enum enum (unnamed at /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumber.h:31:9).kCFNumberSInt32Type = 3 * } */ public static int kCFNumberSInt32Type() { - return (int)3L; + return kCFNumberSInt32Type; + } + + private static class CFNumberGetTypeID { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_LONG ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFNumberGetTypeID"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } - public static MethodHandle CFNumberGetTypeID$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$0,"CFNumberGetTypeID"); + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFTypeID CFNumberGetTypeID(void) + * } + */ + public static FunctionDescriptor CFNumberGetTypeID$descriptor() { + return CFNumberGetTypeID.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFTypeID CFNumberGetTypeID(void) + * } + */ + public static MethodHandle CFNumberGetTypeID$handle() { + return CFNumberGetTypeID.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFTypeID CFNumberGetTypeID(void) + * } + */ + public static MemorySegment CFNumberGetTypeID$address() { + return CFNumberGetTypeID.ADDR; } + /** - * {@snippet : - * CFTypeID CFNumberGetTypeID(); + * {@snippet lang=c : + * extern CFTypeID CFNumberGetTypeID(void) * } */ public static long CFNumberGetTypeID() { - var mh$ = CFNumberGetTypeID$MH(); + var mh$ = CFNumberGetTypeID.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFNumberGetTypeID"); + } return (long)mh$.invokeExact(); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFNumberGetValue$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$2,"CFNumberGetValue"); + + private static class CFNumberGetValue { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_CHAR, + CoreFoundation.C_POINTER, + CoreFoundation.C_LONG, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFNumberGetValue"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr) + * } + */ + public static FunctionDescriptor CFNumberGetValue$descriptor() { + return CFNumberGetValue.DESC; } + /** - * {@snippet : - * Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void* valuePtr); + * Downcall method handle for: + * {@snippet lang=c : + * extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr) + * } + */ + public static MethodHandle CFNumberGetValue$handle() { + return CFNumberGetValue.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr) + * } + */ + public static MemorySegment CFNumberGetValue$address() { + return CFNumberGetValue.ADDR; + } + + /** + * {@snippet lang=c : + * extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr) * } */ public static byte CFNumberGetValue(MemorySegment number, long theType, MemorySegment valuePtr) { - var mh$ = CFNumberGetValue$MH(); + var mh$ = CFNumberGetValue.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFNumberGetValue", number, theType, valuePtr); + } return (byte)mh$.invokeExact(number, theType, valuePtr); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFRunLoopGetCurrent$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$4,"CFRunLoopGetCurrent"); + + private static class CFRunLoopGetCurrent { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFRunLoopGetCurrent"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFRunLoopRef CFRunLoopGetCurrent(void) + * } + */ + public static FunctionDescriptor CFRunLoopGetCurrent$descriptor() { + return CFRunLoopGetCurrent.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFRunLoopRef CFRunLoopGetCurrent(void) + * } + */ + public static MethodHandle CFRunLoopGetCurrent$handle() { + return CFRunLoopGetCurrent.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFRunLoopRef CFRunLoopGetCurrent(void) + * } + */ + public static MemorySegment CFRunLoopGetCurrent$address() { + return CFRunLoopGetCurrent.ADDR; } + /** - * {@snippet : - * CFRunLoopRef CFRunLoopGetCurrent(); + * {@snippet lang=c : + * extern CFRunLoopRef CFRunLoopGetCurrent(void) * } */ public static MemorySegment CFRunLoopGetCurrent() { - var mh$ = CFRunLoopGetCurrent$MH(); + var mh$ = CFRunLoopGetCurrent.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(); + if (TRACE_DOWNCALLS) { + traceDowncall("CFRunLoopGetCurrent"); + } + return (MemorySegment)mh$.invokeExact(); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFRunLoopRun$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$6,"CFRunLoopRun"); + + private static class CFRunLoopRun { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFRunLoopRun"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern void CFRunLoopRun(void) + * } + */ + public static FunctionDescriptor CFRunLoopRun$descriptor() { + return CFRunLoopRun.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern void CFRunLoopRun(void) + * } + */ + public static MethodHandle CFRunLoopRun$handle() { + return CFRunLoopRun.HANDLE; } + /** - * {@snippet : - * void CFRunLoopRun(); + * Address for: + * {@snippet lang=c : + * extern void CFRunLoopRun(void) + * } + */ + public static MemorySegment CFRunLoopRun$address() { + return CFRunLoopRun.ADDR; + } + + /** + * {@snippet lang=c : + * extern void CFRunLoopRun(void) * } */ public static void CFRunLoopRun() { - var mh$ = CFRunLoopRun$MH(); + var mh$ = CFRunLoopRun.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFRunLoopRun"); + } mh$.invokeExact(); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFRunLoopAddSource$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$1,"CFRunLoopAddSource"); + + private static class CFRunLoopAddSource { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFRunLoopAddSource"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static FunctionDescriptor CFRunLoopAddSource$descriptor() { + return CFRunLoopAddSource.DESC; } + /** - * {@snippet : - * void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode); + * Downcall method handle for: + * {@snippet lang=c : + * extern void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static MethodHandle CFRunLoopAddSource$handle() { + return CFRunLoopAddSource.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static MemorySegment CFRunLoopAddSource$address() { + return CFRunLoopAddSource.ADDR; + } + + /** + * {@snippet lang=c : + * extern void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) * } */ public static void CFRunLoopAddSource(MemorySegment rl, MemorySegment source, MemorySegment mode) { - var mh$ = CFRunLoopAddSource$MH(); + var mh$ = CFRunLoopAddSource.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFRunLoopAddSource", rl, source, mode); + } mh$.invokeExact(rl, source, mode); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFRunLoopRemoveSource$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$2,"CFRunLoopRemoveSource"); + + private static class CFRunLoopRemoveSource { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFRunLoopRemoveSource"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode); + * Function descriptor for: + * {@snippet lang=c : + * extern void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static FunctionDescriptor CFRunLoopRemoveSource$descriptor() { + return CFRunLoopRemoveSource.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static MethodHandle CFRunLoopRemoveSource$handle() { + return CFRunLoopRemoveSource.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) + * } + */ + public static MemorySegment CFRunLoopRemoveSource$address() { + return CFRunLoopRemoveSource.ADDR; + } + + /** + * {@snippet lang=c : + * extern void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFRunLoopMode mode) * } */ public static void CFRunLoopRemoveSource(MemorySegment rl, MemorySegment source, MemorySegment mode) { - var mh$ = CFRunLoopRemoveSource$MH(); + var mh$ = CFRunLoopRemoveSource.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFRunLoopRemoveSource", rl, source, mode); + } mh$.invokeExact(rl, source, mode); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFUUIDGetUUIDBytes$MH() { - return RuntimeHelper.requireNonNull(constants$6.const$3,"CFUUIDGetUUIDBytes"); + + private static class CFUUIDGetUUIDBytes { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CFUUIDBytes.layout(), + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFUUIDGetUUIDBytes"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFUUIDBytes CFUUIDGetUUIDBytes(CFUUIDRef uuid) + * } + */ + public static FunctionDescriptor CFUUIDGetUUIDBytes$descriptor() { + return CFUUIDGetUUIDBytes.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFUUIDBytes CFUUIDGetUUIDBytes(CFUUIDRef uuid) + * } + */ + public static MethodHandle CFUUIDGetUUIDBytes$handle() { + return CFUUIDGetUUIDBytes.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFUUIDBytes CFUUIDGetUUIDBytes(CFUUIDRef uuid) + * } + */ + public static MemorySegment CFUUIDGetUUIDBytes$address() { + return CFUUIDGetUUIDBytes.ADDR; } + /** - * {@snippet : - * CFUUIDBytes CFUUIDGetUUIDBytes(CFUUIDRef uuid); + * {@snippet lang=c : + * extern CFUUIDBytes CFUUIDGetUUIDBytes(CFUUIDRef uuid) * } */ public static MemorySegment CFUUIDGetUUIDBytes(SegmentAllocator allocator, MemorySegment uuid) { - var mh$ = CFUUIDGetUUIDBytes$MH(); + var mh$ = CFUUIDGetUUIDBytes.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(allocator, uuid); + if (TRACE_DOWNCALLS) { + traceDowncall("CFUUIDGetUUIDBytes", allocator, uuid); + } + return (MemorySegment)mh$.invokeExact(allocator, uuid); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle CFUUIDCreateFromUUIDBytes$MH() { - return RuntimeHelper.requireNonNull(constants$6.const$5,"CFUUIDCreateFromUUIDBytes"); + + private static class CFUUIDCreateFromUUIDBytes { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CFUUIDBytes.layout() + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFUUIDCreateFromUUIDBytes"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes); + * Function descriptor for: + * {@snippet lang=c : + * extern CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes) + * } + */ + public static FunctionDescriptor CFUUIDCreateFromUUIDBytes$descriptor() { + return CFUUIDCreateFromUUIDBytes.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes) + * } + */ + public static MethodHandle CFUUIDCreateFromUUIDBytes$handle() { + return CFUUIDCreateFromUUIDBytes.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes) + * } + */ + public static MemorySegment CFUUIDCreateFromUUIDBytes$address() { + return CFUUIDCreateFromUUIDBytes.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes) * } */ public static MemorySegment CFUUIDCreateFromUUIDBytes(MemorySegment alloc, MemorySegment bytes) { - var mh$ = CFUUIDCreateFromUUIDBytes$MH(); + var mh$ = CFUUIDCreateFromUUIDBytes.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(alloc, bytes); + if (TRACE_DOWNCALLS) { + traceDowncall("CFUUIDCreateFromUUIDBytes", alloc, bytes); + } + return (MemorySegment)mh$.invokeExact(alloc, bytes); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } -} + private static class CFMessagePortCreateLocal { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFMessagePortCreateLocal"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo) + * } + */ + public static FunctionDescriptor CFMessagePortCreateLocal$descriptor() { + return CFMessagePortCreateLocal.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo) + * } + */ + public static MethodHandle CFMessagePortCreateLocal$handle() { + return CFMessagePortCreateLocal.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo) + * } + */ + public static MemorySegment CFMessagePortCreateLocal$address() { + return CFMessagePortCreateLocal.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo) + * } + */ + public static MemorySegment CFMessagePortCreateLocal(MemorySegment allocator, MemorySegment name, MemorySegment callout, MemorySegment context, MemorySegment shouldFreeInfo) { + var mh$ = CFMessagePortCreateLocal.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFMessagePortCreateLocal", allocator, name, callout, context, shouldFreeInfo); + } + return (MemorySegment)mh$.invokeExact(allocator, name, callout, context, shouldFreeInfo); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static class CFMessagePortCreateRemote { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFMessagePortCreateRemote"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) + * } + */ + public static FunctionDescriptor CFMessagePortCreateRemote$descriptor() { + return CFMessagePortCreateRemote.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) + * } + */ + public static MethodHandle CFMessagePortCreateRemote$handle() { + return CFMessagePortCreateRemote.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) + * } + */ + public static MemorySegment CFMessagePortCreateRemote$address() { + return CFMessagePortCreateRemote.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFMessagePortRef CFMessagePortCreateRemote(CFAllocatorRef allocator, CFStringRef name) + * } + */ + public static MemorySegment CFMessagePortCreateRemote(MemorySegment allocator, MemorySegment name) { + var mh$ = CFMessagePortCreateRemote.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFMessagePortCreateRemote", allocator, name); + } + return (MemorySegment)mh$.invokeExact(allocator, name); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static class CFMessagePortSendRequest { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_INT, + CoreFoundation.C_POINTER, + CoreFoundation.C_INT, + CoreFoundation.C_POINTER, + CoreFoundation.C_DOUBLE, + CoreFoundation.C_DOUBLE, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFMessagePortSendRequest"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnData) + * } + */ + public static FunctionDescriptor CFMessagePortSendRequest$descriptor() { + return CFMessagePortSendRequest.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnData) + * } + */ + public static MethodHandle CFMessagePortSendRequest$handle() { + return CFMessagePortSendRequest.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnData) + * } + */ + public static MemorySegment CFMessagePortSendRequest$address() { + return CFMessagePortSendRequest.ADDR; + } + + /** + * {@snippet lang=c : + * extern SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef data, CFTimeInterval sendTimeout, CFTimeInterval rcvTimeout, CFStringRef replyMode, CFDataRef *returnData) + * } + */ + public static int CFMessagePortSendRequest(MemorySegment remote, int msgid, MemorySegment data, double sendTimeout, double rcvTimeout, MemorySegment replyMode, MemorySegment returnData) { + var mh$ = CFMessagePortSendRequest.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFMessagePortSendRequest", remote, msgid, data, sendTimeout, rcvTimeout, replyMode, returnData); + } + return (int)mh$.invokeExact(remote, msgid, data, sendTimeout, rcvTimeout, replyMode, returnData); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static class CFMessagePortCreateRunLoopSource { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_POINTER, + CoreFoundation.C_LONG + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("CFMessagePortCreateRunLoopSource"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * extern CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef local, CFIndex order) + * } + */ + public static FunctionDescriptor CFMessagePortCreateRunLoopSource$descriptor() { + return CFMessagePortCreateRunLoopSource.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * extern CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef local, CFIndex order) + * } + */ + public static MethodHandle CFMessagePortCreateRunLoopSource$handle() { + return CFMessagePortCreateRunLoopSource.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * extern CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef local, CFIndex order) + * } + */ + public static MemorySegment CFMessagePortCreateRunLoopSource$address() { + return CFMessagePortCreateRunLoopSource.ADDR; + } + + /** + * {@snippet lang=c : + * extern CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef local, CFIndex order) + * } + */ + public static MemorySegment CFMessagePortCreateRunLoopSource(MemorySegment allocator, MemorySegment local, long order) { + var mh$ = CFMessagePortCreateRunLoopSource.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("CFMessagePortCreateRunLoopSource", allocator, local, order); + } + return (MemorySegment)mh$.invokeExact(allocator, local, order); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/RuntimeHelper.java deleted file mode 100644 index 9fb56e43..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/RuntimeHelper.java +++ /dev/null @@ -1,228 +0,0 @@ -package net.codecrete.usb.macos.gen.corefoundation; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { -// System.loadLibrary("CoreFoundation.framework"); -// SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SymbolLookup loaderLookup = SymbolLookup.libraryLookup("CoreFoundation.framework/CoreFoundation", Arena.global()); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$0.java deleted file mode 100644 index ec347d54..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$0.java +++ /dev/null @@ -1,38 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_LONG; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_LONG.withName("location"), - JAVA_LONG.withName("length") - ).withName(""); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("location")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("length")); - static final FunctionDescriptor const$3 = FunctionDescriptor.of(JAVA_LONG, - RuntimeHelper.POINTER - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "CFGetTypeID", - constants$0.const$3 - ); - static final FunctionDescriptor const$5 = FunctionDescriptor.ofVoid( - RuntimeHelper.POINTER - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "CFRelease", - constants$0.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$1.java deleted file mode 100644 index d7550d1a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$1.java +++ /dev/null @@ -1,46 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_LONG; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_LONG); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "CFStringGetTypeID", - constants$1.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - JAVA_LONG - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "CFStringCreateWithCharacters", - constants$1.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "CFStringGetLength", - constants$0.const$3 - ); - static final FunctionDescriptor const$5 = FunctionDescriptor.ofVoid( - RuntimeHelper.POINTER, - MemoryLayout.structLayout( - JAVA_LONG.withName("location"), - JAVA_LONG.withName("length") - ).withName(""), - RuntimeHelper.POINTER - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "CFStringGetCharacters", - constants$1.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$2.java deleted file mode 100644 index 7db1c6cc..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$2.java +++ /dev/null @@ -1,39 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_LONG; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - "CFNumberGetTypeID", - constants$1.const$0 - ); - static final FunctionDescriptor const$1 = FunctionDescriptor.of(JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_LONG, - RuntimeHelper.POINTER - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "CFNumberGetValue", - constants$2.const$1 - ); - static final FunctionDescriptor const$3 = FunctionDescriptor.of(RuntimeHelper.POINTER); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "CFRunLoopGetCurrent", - constants$2.const$3 - ); - static final FunctionDescriptor const$5 = FunctionDescriptor.ofVoid(); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "CFRunLoopRun", - constants$2.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$3.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$3.java deleted file mode 100644 index 1a0a9ed3..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$3.java +++ /dev/null @@ -1,51 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -final class constants$3 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$3() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.ofVoid( - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "CFRunLoopAddSource", - constants$3.const$0 - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "CFRunLoopRemoveSource", - constants$3.const$0 - ); - static final StructLayout const$3 = MemoryLayout.structLayout( - JAVA_BYTE.withName("byte0"), - JAVA_BYTE.withName("byte1"), - JAVA_BYTE.withName("byte2"), - JAVA_BYTE.withName("byte3"), - JAVA_BYTE.withName("byte4"), - JAVA_BYTE.withName("byte5"), - JAVA_BYTE.withName("byte6"), - JAVA_BYTE.withName("byte7"), - JAVA_BYTE.withName("byte8"), - JAVA_BYTE.withName("byte9"), - JAVA_BYTE.withName("byte10"), - JAVA_BYTE.withName("byte11"), - JAVA_BYTE.withName("byte12"), - JAVA_BYTE.withName("byte13"), - JAVA_BYTE.withName("byte14"), - JAVA_BYTE.withName("byte15") - ).withName(""); - static final VarHandle const$4 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte0")); - static final VarHandle const$5 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte1")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$4.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$4.java deleted file mode 100644 index 52637eb6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$4.java +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$4 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$4() {} - static final VarHandle const$0 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte2")); - static final VarHandle const$1 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte3")); - static final VarHandle const$2 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte4")); - static final VarHandle const$3 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte5")); - static final VarHandle const$4 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte6")); - static final VarHandle const$5 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte7")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$5.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$5.java deleted file mode 100644 index 075afe34..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$5.java +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$5 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$5() {} - static final VarHandle const$0 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte8")); - static final VarHandle const$1 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte9")); - static final VarHandle const$2 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte10")); - static final VarHandle const$3 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte11")); - static final VarHandle const$4 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte12")); - static final VarHandle const$5 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte13")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$6.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$6.java deleted file mode 100644 index 748e65c4..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/corefoundation/constants$6.java +++ /dev/null @@ -1,68 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.corefoundation; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -final class constants$6 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$6() {} - static final VarHandle const$0 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte14")); - static final VarHandle const$1 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("byte15")); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(MemoryLayout.structLayout( - JAVA_BYTE.withName("byte0"), - JAVA_BYTE.withName("byte1"), - JAVA_BYTE.withName("byte2"), - JAVA_BYTE.withName("byte3"), - JAVA_BYTE.withName("byte4"), - JAVA_BYTE.withName("byte5"), - JAVA_BYTE.withName("byte6"), - JAVA_BYTE.withName("byte7"), - JAVA_BYTE.withName("byte8"), - JAVA_BYTE.withName("byte9"), - JAVA_BYTE.withName("byte10"), - JAVA_BYTE.withName("byte11"), - JAVA_BYTE.withName("byte12"), - JAVA_BYTE.withName("byte13"), - JAVA_BYTE.withName("byte14"), - JAVA_BYTE.withName("byte15") - ).withName(""), - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "CFUUIDGetUUIDBytes", - constants$6.const$2 - ); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - MemoryLayout.structLayout( - JAVA_BYTE.withName("byte0"), - JAVA_BYTE.withName("byte1"), - JAVA_BYTE.withName("byte2"), - JAVA_BYTE.withName("byte3"), - JAVA_BYTE.withName("byte4"), - JAVA_BYTE.withName("byte5"), - JAVA_BYTE.withName("byte6"), - JAVA_BYTE.withName("byte7"), - JAVA_BYTE.withName("byte8"), - JAVA_BYTE.withName("byte9"), - JAVA_BYTE.withName("byte10"), - JAVA_BYTE.withName("byte11"), - JAVA_BYTE.withName("byte12"), - JAVA_BYTE.withName("byte13"), - JAVA_BYTE.withName("byte14"), - JAVA_BYTE.withName("byte15") - ).withName("") - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "CFUUIDCreateFromUUIDBytes", - constants$6.const$4 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/CFUUIDBytes.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/CFUUIDBytes.java new file mode 100644 index 00000000..b1ab37eb --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/CFUUIDBytes.java @@ -0,0 +1,817 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.iokit; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +/** + * {@snippet lang=c : + * struct { + * UInt8 byte0; + * UInt8 byte1; + * UInt8 byte2; + * UInt8 byte3; + * UInt8 byte4; + * UInt8 byte5; + * UInt8 byte6; + * UInt8 byte7; + * UInt8 byte8; + * UInt8 byte9; + * UInt8 byte10; + * UInt8 byte11; + * UInt8 byte12; + * UInt8 byte13; + * UInt8 byte14; + * UInt8 byte15; + * } + * } + */ +public class CFUUIDBytes { + + CFUUIDBytes() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_CHAR.withName("byte0"), + IOKit.C_CHAR.withName("byte1"), + IOKit.C_CHAR.withName("byte2"), + IOKit.C_CHAR.withName("byte3"), + IOKit.C_CHAR.withName("byte4"), + IOKit.C_CHAR.withName("byte5"), + IOKit.C_CHAR.withName("byte6"), + IOKit.C_CHAR.withName("byte7"), + IOKit.C_CHAR.withName("byte8"), + IOKit.C_CHAR.withName("byte9"), + IOKit.C_CHAR.withName("byte10"), + IOKit.C_CHAR.withName("byte11"), + IOKit.C_CHAR.withName("byte12"), + IOKit.C_CHAR.withName("byte13"), + IOKit.C_CHAR.withName("byte14"), + IOKit.C_CHAR.withName("byte15") + ).withName("CFUUIDBytes"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; + } + + private static final OfByte byte0$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte0")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static final OfByte byte0$layout() { + return byte0$LAYOUT; + } + + private static final long byte0$OFFSET = $LAYOUT.byteOffset(groupElement("byte0")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static final long byte0$offset() { + return byte0$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static byte byte0(MemorySegment struct) { + return struct.get(byte0$LAYOUT, byte0$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte0 + * } + */ + public static void byte0(MemorySegment struct, byte fieldValue) { + struct.set(byte0$LAYOUT, byte0$OFFSET, fieldValue); + } + + private static final OfByte byte1$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte1")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static final OfByte byte1$layout() { + return byte1$LAYOUT; + } + + private static final long byte1$OFFSET = $LAYOUT.byteOffset(groupElement("byte1")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static final long byte1$offset() { + return byte1$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static byte byte1(MemorySegment struct) { + return struct.get(byte1$LAYOUT, byte1$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte1 + * } + */ + public static void byte1(MemorySegment struct, byte fieldValue) { + struct.set(byte1$LAYOUT, byte1$OFFSET, fieldValue); + } + + private static final OfByte byte2$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte2")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static final OfByte byte2$layout() { + return byte2$LAYOUT; + } + + private static final long byte2$OFFSET = $LAYOUT.byteOffset(groupElement("byte2")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static final long byte2$offset() { + return byte2$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static byte byte2(MemorySegment struct) { + return struct.get(byte2$LAYOUT, byte2$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte2 + * } + */ + public static void byte2(MemorySegment struct, byte fieldValue) { + struct.set(byte2$LAYOUT, byte2$OFFSET, fieldValue); + } + + private static final OfByte byte3$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte3")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static final OfByte byte3$layout() { + return byte3$LAYOUT; + } + + private static final long byte3$OFFSET = $LAYOUT.byteOffset(groupElement("byte3")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static final long byte3$offset() { + return byte3$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static byte byte3(MemorySegment struct) { + return struct.get(byte3$LAYOUT, byte3$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte3 + * } + */ + public static void byte3(MemorySegment struct, byte fieldValue) { + struct.set(byte3$LAYOUT, byte3$OFFSET, fieldValue); + } + + private static final OfByte byte4$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte4")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static final OfByte byte4$layout() { + return byte4$LAYOUT; + } + + private static final long byte4$OFFSET = $LAYOUT.byteOffset(groupElement("byte4")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static final long byte4$offset() { + return byte4$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static byte byte4(MemorySegment struct) { + return struct.get(byte4$LAYOUT, byte4$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte4 + * } + */ + public static void byte4(MemorySegment struct, byte fieldValue) { + struct.set(byte4$LAYOUT, byte4$OFFSET, fieldValue); + } + + private static final OfByte byte5$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte5")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static final OfByte byte5$layout() { + return byte5$LAYOUT; + } + + private static final long byte5$OFFSET = $LAYOUT.byteOffset(groupElement("byte5")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static final long byte5$offset() { + return byte5$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static byte byte5(MemorySegment struct) { + return struct.get(byte5$LAYOUT, byte5$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte5 + * } + */ + public static void byte5(MemorySegment struct, byte fieldValue) { + struct.set(byte5$LAYOUT, byte5$OFFSET, fieldValue); + } + + private static final OfByte byte6$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte6")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static final OfByte byte6$layout() { + return byte6$LAYOUT; + } + + private static final long byte6$OFFSET = $LAYOUT.byteOffset(groupElement("byte6")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static final long byte6$offset() { + return byte6$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static byte byte6(MemorySegment struct) { + return struct.get(byte6$LAYOUT, byte6$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte6 + * } + */ + public static void byte6(MemorySegment struct, byte fieldValue) { + struct.set(byte6$LAYOUT, byte6$OFFSET, fieldValue); + } + + private static final OfByte byte7$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte7")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static final OfByte byte7$layout() { + return byte7$LAYOUT; + } + + private static final long byte7$OFFSET = $LAYOUT.byteOffset(groupElement("byte7")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static final long byte7$offset() { + return byte7$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static byte byte7(MemorySegment struct) { + return struct.get(byte7$LAYOUT, byte7$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte7 + * } + */ + public static void byte7(MemorySegment struct, byte fieldValue) { + struct.set(byte7$LAYOUT, byte7$OFFSET, fieldValue); + } + + private static final OfByte byte8$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte8")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static final OfByte byte8$layout() { + return byte8$LAYOUT; + } + + private static final long byte8$OFFSET = $LAYOUT.byteOffset(groupElement("byte8")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static final long byte8$offset() { + return byte8$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static byte byte8(MemorySegment struct) { + return struct.get(byte8$LAYOUT, byte8$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte8 + * } + */ + public static void byte8(MemorySegment struct, byte fieldValue) { + struct.set(byte8$LAYOUT, byte8$OFFSET, fieldValue); + } + + private static final OfByte byte9$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte9")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static final OfByte byte9$layout() { + return byte9$LAYOUT; + } + + private static final long byte9$OFFSET = $LAYOUT.byteOffset(groupElement("byte9")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static final long byte9$offset() { + return byte9$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static byte byte9(MemorySegment struct) { + return struct.get(byte9$LAYOUT, byte9$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte9 + * } + */ + public static void byte9(MemorySegment struct, byte fieldValue) { + struct.set(byte9$LAYOUT, byte9$OFFSET, fieldValue); + } + + private static final OfByte byte10$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte10")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static final OfByte byte10$layout() { + return byte10$LAYOUT; + } + + private static final long byte10$OFFSET = $LAYOUT.byteOffset(groupElement("byte10")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static final long byte10$offset() { + return byte10$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static byte byte10(MemorySegment struct) { + return struct.get(byte10$LAYOUT, byte10$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte10 + * } + */ + public static void byte10(MemorySegment struct, byte fieldValue) { + struct.set(byte10$LAYOUT, byte10$OFFSET, fieldValue); + } + + private static final OfByte byte11$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte11")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static final OfByte byte11$layout() { + return byte11$LAYOUT; + } + + private static final long byte11$OFFSET = $LAYOUT.byteOffset(groupElement("byte11")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static final long byte11$offset() { + return byte11$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static byte byte11(MemorySegment struct) { + return struct.get(byte11$LAYOUT, byte11$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte11 + * } + */ + public static void byte11(MemorySegment struct, byte fieldValue) { + struct.set(byte11$LAYOUT, byte11$OFFSET, fieldValue); + } + + private static final OfByte byte12$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte12")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static final OfByte byte12$layout() { + return byte12$LAYOUT; + } + + private static final long byte12$OFFSET = $LAYOUT.byteOffset(groupElement("byte12")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static final long byte12$offset() { + return byte12$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static byte byte12(MemorySegment struct) { + return struct.get(byte12$LAYOUT, byte12$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte12 + * } + */ + public static void byte12(MemorySegment struct, byte fieldValue) { + struct.set(byte12$LAYOUT, byte12$OFFSET, fieldValue); + } + + private static final OfByte byte13$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte13")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static final OfByte byte13$layout() { + return byte13$LAYOUT; + } + + private static final long byte13$OFFSET = $LAYOUT.byteOffset(groupElement("byte13")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static final long byte13$offset() { + return byte13$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static byte byte13(MemorySegment struct) { + return struct.get(byte13$LAYOUT, byte13$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte13 + * } + */ + public static void byte13(MemorySegment struct, byte fieldValue) { + struct.set(byte13$LAYOUT, byte13$OFFSET, fieldValue); + } + + private static final OfByte byte14$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte14")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static final OfByte byte14$layout() { + return byte14$LAYOUT; + } + + private static final long byte14$OFFSET = $LAYOUT.byteOffset(groupElement("byte14")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static final long byte14$offset() { + return byte14$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static byte byte14(MemorySegment struct) { + return struct.get(byte14$LAYOUT, byte14$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte14 + * } + */ + public static void byte14(MemorySegment struct, byte fieldValue) { + struct.set(byte14$LAYOUT, byte14$OFFSET, fieldValue); + } + + private static final OfByte byte15$LAYOUT = (OfByte)$LAYOUT.select(groupElement("byte15")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static final OfByte byte15$layout() { + return byte15$LAYOUT; + } + + private static final long byte15$OFFSET = $LAYOUT.byteOffset(groupElement("byte15")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static final long byte15$offset() { + return byte15$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static byte byte15(MemorySegment struct) { + return struct.get(byte15$LAYOUT, byte15$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * UInt8 byte15 + * } + */ + public static void byte15(MemorySegment struct, byte fieldValue) { + struct.set(byte15$LAYOUT, byte15$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); + } + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); + } + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterface.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterface.java deleted file mode 100644 index 0b23bb51..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -/** - * {@snippet : - * typedef struct IOCFPlugInInterfaceStruct IOCFPlugInInterface; - * } - */ -public final class IOCFPlugInInterface extends IOCFPlugInInterfaceStruct { - - // Suppresses default constructor, ensuring non-instantiability. - private IOCFPlugInInterface() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterfaceStruct.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterfaceStruct.java index 92d54afc..74f3414d 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterfaceStruct.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOCFPlugInInterfaceStruct.java @@ -2,436 +2,760 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct IOCFPlugInInterfaceStruct { - * void* _reserved; - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); - * ULONG (*AddRef)(void*); - * ULONG (*Release)(void*); + * void *_reserved; + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *); + * ULONG (*AddRef)(void *); + * ULONG (*Release)(void *); * UInt16 version; * UInt16 revision; - * IOReturn (*Probe)(void*,CFDictionaryRef,io_service_t,SInt32*); - * IOReturn (*Start)(void*,CFDictionaryRef,io_service_t); - * IOReturn (*Stop)(void*); - * }; + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *); + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t); + * IOReturn (*Stop)(void *); + * } * } */ public class IOCFPlugInInterfaceStruct { - public static MemoryLayout $LAYOUT() { - return constants$40.const$2; + IOCFPlugInInterfaceStruct() { + // Should not be called directly } - public static VarHandle _reserved$VH() { - return constants$40.const$3; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_POINTER.withName("_reserved"), + IOKit.C_POINTER.withName("QueryInterface"), + IOKit.C_POINTER.withName("AddRef"), + IOKit.C_POINTER.withName("Release"), + IOKit.C_SHORT.withName("version"), + IOKit.C_SHORT.withName("revision"), + MemoryLayout.paddingLayout(4), + IOKit.C_POINTER.withName("Probe"), + IOKit.C_POINTER.withName("Start"), + IOKit.C_POINTER.withName("Stop") + ).withName("IOCFPlugInInterfaceStruct"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final AddressLayout _reserved$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("_reserved")); + /** - * Getter for field: - * {@snippet : - * void* _reserved; + * Layout for field: + * {@snippet lang=c : + * void *_reserved * } */ - public static MemorySegment _reserved$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$40.const$3.get(seg); + public static final AddressLayout _reserved$layout() { + return _reserved$LAYOUT; } + + private static final long _reserved$OFFSET = $LAYOUT.byteOffset(groupElement("_reserved")); + /** - * Setter for field: - * {@snippet : - * void* _reserved; + * Offset for field: + * {@snippet lang=c : + * void *_reserved * } */ - public static void _reserved$set(MemorySegment seg, MemorySegment x) { - constants$40.const$3.set(seg, x); + public static final long _reserved$offset() { + return _reserved$OFFSET; } - public static MemorySegment _reserved$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$40.const$3.get(seg.asSlice(index*sizeof())); + + /** + * Getter for field: + * {@snippet lang=c : + * void *_reserved + * } + */ + public static MemorySegment _reserved(MemorySegment struct) { + return struct.get(_reserved$LAYOUT, _reserved$OFFSET); } - public static void _reserved$set(MemorySegment seg, long index, MemorySegment x) { - constants$40.const$3.set(seg.asSlice(index*sizeof()), x); + + /** + * Setter for field: + * {@snippet lang=c : + * void *_reserved + * } + */ + public static void _reserved(MemorySegment struct, MemorySegment fieldValue) { + struct.set(_reserved$LAYOUT, _reserved$OFFSET, fieldValue); } + /** - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public interface QueryInterface { + public final static class QueryInterface { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(QueryInterface fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$40.const$4, fi, constants$5.const$1, scope); + private QueryInterface() { + // Should not be called directly } - static QueryInterface ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$5.const$3.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + CFUUIDBytes.layout(), + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle QueryInterface$VH() { - return constants$40.const$5; + private static final AddressLayout QueryInterface$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("QueryInterface")); + + /** + * Layout for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) + * } + */ + public static final AddressLayout QueryInterface$layout() { + return QueryInterface$LAYOUT; } + + private static final long QueryInterface$OFFSET = $LAYOUT.byteOffset(groupElement("QueryInterface")); + + /** + * Offset for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) + * } + */ + public static final long QueryInterface$offset() { + return QueryInterface$OFFSET; + } + /** * Getter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static MemorySegment QueryInterface$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$40.const$5.get(seg); + public static MemorySegment QueryInterface(MemorySegment struct) { + return struct.get(QueryInterface$LAYOUT, QueryInterface$OFFSET); } + /** * Setter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static void QueryInterface$set(MemorySegment seg, MemorySegment x) { - constants$40.const$5.set(seg, x); - } - public static MemorySegment QueryInterface$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$40.const$5.get(seg.asSlice(index*sizeof())); - } - public static void QueryInterface$set(MemorySegment seg, long index, MemorySegment x) { - constants$40.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static QueryInterface QueryInterface(MemorySegment segment, Arena scope) { - return QueryInterface.ofAddress(QueryInterface$get(segment), scope); + public static void QueryInterface(MemorySegment struct, MemorySegment fieldValue) { + struct.set(QueryInterface$LAYOUT, QueryInterface$OFFSET, fieldValue); } + /** - * {@snippet : - * ULONG (*AddRef)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public interface AddRef { + public final static class AddRef { + + private AddRef() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(AddRef fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$41.const$0, fi, constants$5.const$5, scope); + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static AddRef ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle AddRef$VH() { - return constants$41.const$1; + private static final AddressLayout AddRef$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("AddRef")); + + /** + * Layout for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) + * } + */ + public static final AddressLayout AddRef$layout() { + return AddRef$LAYOUT; + } + + private static final long AddRef$OFFSET = $LAYOUT.byteOffset(groupElement("AddRef")); + + /** + * Offset for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) + * } + */ + public static final long AddRef$offset() { + return AddRef$OFFSET; } + /** * Getter for field: - * {@snippet : - * ULONG (*AddRef)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static MemorySegment AddRef$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$41.const$1.get(seg); + public static MemorySegment AddRef(MemorySegment struct) { + return struct.get(AddRef$LAYOUT, AddRef$OFFSET); } + /** * Setter for field: - * {@snippet : - * ULONG (*AddRef)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static void AddRef$set(MemorySegment seg, MemorySegment x) { - constants$41.const$1.set(seg, x); - } - public static MemorySegment AddRef$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$41.const$1.get(seg.asSlice(index*sizeof())); - } - public static void AddRef$set(MemorySegment seg, long index, MemorySegment x) { - constants$41.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static AddRef AddRef(MemorySegment segment, Arena scope) { - return AddRef.ofAddress(AddRef$get(segment), scope); + public static void AddRef(MemorySegment struct, MemorySegment fieldValue) { + struct.set(AddRef$LAYOUT, AddRef$OFFSET, fieldValue); } + /** - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public interface Release { + public final static class Release { - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(Release fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$41.const$2, fi, constants$5.const$5, scope); + private Release() { + // Should not be called directly } - static Release ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle Release$VH() { - return constants$41.const$3; + private static final AddressLayout Release$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Release")); + + /** + * Layout for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) + * } + */ + public static final AddressLayout Release$layout() { + return Release$LAYOUT; } + + private static final long Release$OFFSET = $LAYOUT.byteOffset(groupElement("Release")); + + /** + * Offset for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) + * } + */ + public static final long Release$offset() { + return Release$OFFSET; + } + /** * Getter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static MemorySegment Release$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$41.const$3.get(seg); + public static MemorySegment Release(MemorySegment struct) { + return struct.get(Release$LAYOUT, Release$OFFSET); } + /** * Setter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static void Release$set(MemorySegment seg, MemorySegment x) { - constants$41.const$3.set(seg, x); - } - public static MemorySegment Release$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$41.const$3.get(seg.asSlice(index*sizeof())); + public static void Release(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Release$LAYOUT, Release$OFFSET, fieldValue); } - public static void Release$set(MemorySegment seg, long index, MemorySegment x) { - constants$41.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static Release Release(MemorySegment segment, Arena scope) { - return Release.ofAddress(Release$get(segment), scope); + + private static final OfShort version$LAYOUT = (OfShort)$LAYOUT.select(groupElement("version")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 version + * } + */ + public static final OfShort version$layout() { + return version$LAYOUT; } - public static VarHandle version$VH() { - return constants$41.const$4; + + private static final long version$OFFSET = $LAYOUT.byteOffset(groupElement("version")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 version + * } + */ + public static final long version$offset() { + return version$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 version; + * {@snippet lang=c : + * UInt16 version * } */ - public static short version$get(MemorySegment seg) { - return (short)constants$41.const$4.get(seg); + public static short version(MemorySegment struct) { + return struct.get(version$LAYOUT, version$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 version; + * {@snippet lang=c : + * UInt16 version * } */ - public static void version$set(MemorySegment seg, short x) { - constants$41.const$4.set(seg, x); - } - public static short version$get(MemorySegment seg, long index) { - return (short)constants$41.const$4.get(seg.asSlice(index*sizeof())); + public static void version(MemorySegment struct, short fieldValue) { + struct.set(version$LAYOUT, version$OFFSET, fieldValue); } - public static void version$set(MemorySegment seg, long index, short x) { - constants$41.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort revision$LAYOUT = (OfShort)$LAYOUT.select(groupElement("revision")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 revision + * } + */ + public static final OfShort revision$layout() { + return revision$LAYOUT; } - public static VarHandle revision$VH() { - return constants$41.const$5; + + private static final long revision$OFFSET = $LAYOUT.byteOffset(groupElement("revision")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 revision + * } + */ + public static final long revision$offset() { + return revision$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 revision; + * {@snippet lang=c : + * UInt16 revision * } */ - public static short revision$get(MemorySegment seg) { - return (short)constants$41.const$5.get(seg); + public static short revision(MemorySegment struct) { + return struct.get(revision$LAYOUT, revision$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 revision; + * {@snippet lang=c : + * UInt16 revision * } */ - public static void revision$set(MemorySegment seg, short x) { - constants$41.const$5.set(seg, x); - } - public static short revision$get(MemorySegment seg, long index) { - return (short)constants$41.const$5.get(seg.asSlice(index*sizeof())); - } - public static void revision$set(MemorySegment seg, long index, short x) { - constants$41.const$5.set(seg.asSlice(index*sizeof()), x); + public static void revision(MemorySegment struct, short fieldValue) { + struct.set(revision$LAYOUT, revision$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*Probe)(void*,CFDictionaryRef,io_service_t,SInt32*); + * {@snippet lang=c : + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *) * } */ - public interface Probe { + public final static class Probe { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, int _x2, java.lang.foreign.MemorySegment _x3); - static MemorySegment allocate(Probe fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$42.const$1, fi, constants$42.const$0, scope); + private Probe() { + // Should not be called directly } - static Probe ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, int __x2, java.lang.foreign.MemorySegment __x3) -> { - try { - return (int)constants$42.const$2.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, int _x2, MemorySegment _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle Probe$VH() { - return constants$42.const$3; + private static final AddressLayout Probe$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Probe")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *) + * } + */ + public static final AddressLayout Probe$layout() { + return Probe$LAYOUT; } + + private static final long Probe$OFFSET = $LAYOUT.byteOffset(groupElement("Probe")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *) + * } + */ + public static final long Probe$offset() { + return Probe$OFFSET; + } + /** * Getter for field: - * {@snippet : - * IOReturn (*Probe)(void*,CFDictionaryRef,io_service_t,SInt32*); + * {@snippet lang=c : + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *) * } */ - public static MemorySegment Probe$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$42.const$3.get(seg); + public static MemorySegment Probe(MemorySegment struct) { + return struct.get(Probe$LAYOUT, Probe$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*Probe)(void*,CFDictionaryRef,io_service_t,SInt32*); + * {@snippet lang=c : + * IOReturn (*Probe)(void *, CFDictionaryRef, io_service_t, SInt32 *) * } */ - public static void Probe$set(MemorySegment seg, MemorySegment x) { - constants$42.const$3.set(seg, x); - } - public static MemorySegment Probe$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$42.const$3.get(seg.asSlice(index*sizeof())); - } - public static void Probe$set(MemorySegment seg, long index, MemorySegment x) { - constants$42.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static Probe Probe(MemorySegment segment, Arena scope) { - return Probe.ofAddress(Probe$get(segment), scope); + public static void Probe(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Probe$LAYOUT, Probe$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*Start)(void*,CFDictionaryRef,io_service_t); + * {@snippet lang=c : + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t) * } */ - public interface Start { + public final static class Start { + + private Start() { + // Should not be called directly + } - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, int _x2); - static MemorySegment allocate(Start fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$42.const$5, fi, constants$42.const$4, scope); + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static Start ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, int __x2) -> { - try { - return (int)constants$43.const$0.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, int _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle Start$VH() { - return constants$43.const$1; + private static final AddressLayout Start$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Start")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t) + * } + */ + public static final AddressLayout Start$layout() { + return Start$LAYOUT; + } + + private static final long Start$OFFSET = $LAYOUT.byteOffset(groupElement("Start")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t) + * } + */ + public static final long Start$offset() { + return Start$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*Start)(void*,CFDictionaryRef,io_service_t); + * {@snippet lang=c : + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t) * } */ - public static MemorySegment Start$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$43.const$1.get(seg); + public static MemorySegment Start(MemorySegment struct) { + return struct.get(Start$LAYOUT, Start$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*Start)(void*,CFDictionaryRef,io_service_t); + * {@snippet lang=c : + * IOReturn (*Start)(void *, CFDictionaryRef, io_service_t) * } */ - public static void Start$set(MemorySegment seg, MemorySegment x) { - constants$43.const$1.set(seg, x); - } - public static MemorySegment Start$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$43.const$1.get(seg.asSlice(index*sizeof())); - } - public static void Start$set(MemorySegment seg, long index, MemorySegment x) { - constants$43.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static Start Start(MemorySegment segment, Arena scope) { - return Start.ofAddress(Start$get(segment), scope); + public static void Start(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Start$LAYOUT, Start$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*Stop)(void*); + * {@snippet lang=c : + * IOReturn (*Stop)(void *) * } */ - public interface Stop { + public final static class Stop { + + private Stop() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(Stop fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$43.const$2, fi, constants$5.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static Stop ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle Stop$VH() { - return constants$43.const$3; + private static final AddressLayout Stop$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Stop")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*Stop)(void *) + * } + */ + public static final AddressLayout Stop$layout() { + return Stop$LAYOUT; } + + private static final long Stop$OFFSET = $LAYOUT.byteOffset(groupElement("Stop")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*Stop)(void *) + * } + */ + public static final long Stop$offset() { + return Stop$OFFSET; + } + /** * Getter for field: - * {@snippet : - * IOReturn (*Stop)(void*); + * {@snippet lang=c : + * IOReturn (*Stop)(void *) * } */ - public static MemorySegment Stop$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$43.const$3.get(seg); + public static MemorySegment Stop(MemorySegment struct) { + return struct.get(Stop$LAYOUT, Stop$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*Stop)(void*); + * {@snippet lang=c : + * IOReturn (*Stop)(void *) * } */ - public static void Stop$set(MemorySegment seg, MemorySegment x) { - constants$43.const$3.set(seg, x); + public static void Stop(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Stop$LAYOUT, Stop$OFFSET, fieldValue); } - public static MemorySegment Stop$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$43.const$3.get(seg.asSlice(index*sizeof())); + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static void Stop$set(MemorySegment seg, long index, MemorySegment x) { - constants$43.const$3.set(seg.asSlice(index*sizeof()), x); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); + } + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static Stop Stop(MemorySegment segment, Arena scope) { - return Stop.ofAddress(Stop$get(segment), scope); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit$shared.java new file mode 100644 index 00000000..c3328897 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.iokit; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class IOKit$shared { + + IOKit$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit.java index f03e1d08..0eb5e6dc 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOKit.java @@ -2,301 +2,769 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class IOKit { +import static java.lang.foreign.MemoryLayout.PathElement.*; - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; +public class IOKit extends IOKit$shared { + + IOKit() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.libraryLookup("/System/Library/Frameworks/IOKit.framework/IOKit", LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + + private static final int kIOUSBFindInterfaceDontCare = (int)65535L; /** - * {@snippet : - * enum .kIOUSBFindInterfaceDontCare = 65535; + * {@snippet lang=c : + * enum enum (unnamed at /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/usb/USB.h:898:1).kIOUSBFindInterfaceDontCare = 65535 * } */ public static int kIOUSBFindInterfaceDontCare() { - return (int)65535L; + return kIOUSBFindInterfaceDontCare; } + private static final int kUSBReEnumerateCaptureDeviceMask = (int)1073741824L; /** - * {@snippet : - * enum .kUSBReEnumerateCaptureDeviceMask = 1073741824; + * {@snippet lang=c : + * enum USBReEnumerateOptions.kUSBReEnumerateCaptureDeviceMask = 1073741824 * } */ public static int kUSBReEnumerateCaptureDeviceMask() { - return (int)1073741824L; + return kUSBReEnumerateCaptureDeviceMask; } + private static final int kUSBReEnumerateReleaseDeviceMask = (int)536870912L; /** - * {@snippet : - * enum .kUSBReEnumerateReleaseDeviceMask = 536870912; + * {@snippet lang=c : + * enum USBReEnumerateOptions.kUSBReEnumerateReleaseDeviceMask = 536870912 * } */ public static int kUSBReEnumerateReleaseDeviceMask() { - return (int)536870912L; + return kUSBReEnumerateReleaseDeviceMask; } - public static MemoryLayout kCFRunLoopDefaultMode$LAYOUT() { - return RuntimeHelper.POINTER; + + private static class kCFRunLoopDefaultMode$constants { + public static final AddressLayout LAYOUT = IOKit.C_POINTER; + public static final MemorySegment SEGMENT = SYMBOL_LOOKUP.findOrThrow("kCFRunLoopDefaultMode").reinterpret(LAYOUT.byteSize()); } - public static VarHandle kCFRunLoopDefaultMode$VH() { - return constants$2.const$1; + + /** + * Layout for variable: + * {@snippet lang=c : + * extern const CFRunLoopMode kCFRunLoopDefaultMode + * } + */ + public static AddressLayout kCFRunLoopDefaultMode$layout() { + return kCFRunLoopDefaultMode$constants.LAYOUT; } - public static MemorySegment kCFRunLoopDefaultMode$SEGMENT() { - return RuntimeHelper.requireNonNull(constants$2.const$2,"kCFRunLoopDefaultMode"); + + /** + * Segment for variable: + * {@snippet lang=c : + * extern const CFRunLoopMode kCFRunLoopDefaultMode + * } + */ + public static MemorySegment kCFRunLoopDefaultMode$segment() { + return kCFRunLoopDefaultMode$constants.SEGMENT; } + /** * Getter for variable: - * {@snippet : - * const CFRunLoopMode kCFRunLoopDefaultMode; + * {@snippet lang=c : + * extern const CFRunLoopMode kCFRunLoopDefaultMode * } */ - public static MemorySegment kCFRunLoopDefaultMode$get() { - return (java.lang.foreign.MemorySegment) constants$2.const$1.get(RuntimeHelper.requireNonNull(constants$2.const$2, "kCFRunLoopDefaultMode")); + public static MemorySegment kCFRunLoopDefaultMode() { + return kCFRunLoopDefaultMode$constants.SEGMENT.get(kCFRunLoopDefaultMode$constants.LAYOUT, 0L); } + /** * Setter for variable: - * {@snippet : - * const CFRunLoopMode kCFRunLoopDefaultMode; + * {@snippet lang=c : + * extern const CFRunLoopMode kCFRunLoopDefaultMode * } */ - public static void kCFRunLoopDefaultMode$set(MemorySegment x) { - constants$2.const$1.set(RuntimeHelper.requireNonNull(constants$2.const$2, "kCFRunLoopDefaultMode"), x); + public static void kCFRunLoopDefaultMode(MemorySegment varValue) { + kCFRunLoopDefaultMode$constants.SEGMENT.set(kCFRunLoopDefaultMode$constants.LAYOUT, 0L, varValue); } - public static MemoryLayout kIOMasterPortDefault$LAYOUT() { - return JAVA_INT; + + private static class kIOMasterPortDefault$constants { + public static final OfInt LAYOUT = IOKit.C_INT; + public static final MemorySegment SEGMENT = SYMBOL_LOOKUP.findOrThrow("kIOMasterPortDefault").reinterpret(LAYOUT.byteSize()); } - public static VarHandle kIOMasterPortDefault$VH() { - return constants$2.const$3; + + /** + * Layout for variable: + * {@snippet lang=c : + * extern const mach_port_t kIOMasterPortDefault + * } + */ + public static OfInt kIOMasterPortDefault$layout() { + return kIOMasterPortDefault$constants.LAYOUT; } - public static MemorySegment kIOMasterPortDefault$SEGMENT() { - return RuntimeHelper.requireNonNull(constants$2.const$4,"kIOMasterPortDefault"); + + /** + * Segment for variable: + * {@snippet lang=c : + * extern const mach_port_t kIOMasterPortDefault + * } + */ + public static MemorySegment kIOMasterPortDefault$segment() { + return kIOMasterPortDefault$constants.SEGMENT; } + /** * Getter for variable: - * {@snippet : - * const mach_port_t kIOMasterPortDefault; + * {@snippet lang=c : + * extern const mach_port_t kIOMasterPortDefault * } */ - public static int kIOMasterPortDefault$get() { - return (int) constants$2.const$3.get(RuntimeHelper.requireNonNull(constants$2.const$4, "kIOMasterPortDefault")); + public static int kIOMasterPortDefault() { + return kIOMasterPortDefault$constants.SEGMENT.get(kIOMasterPortDefault$constants.LAYOUT, 0L); } + /** * Setter for variable: - * {@snippet : - * const mach_port_t kIOMasterPortDefault; + * {@snippet lang=c : + * extern const mach_port_t kIOMasterPortDefault * } */ - public static void kIOMasterPortDefault$set(int x) { - constants$2.const$3.set(RuntimeHelper.requireNonNull(constants$2.const$4, "kIOMasterPortDefault"), x); + public static void kIOMasterPortDefault(int varValue) { + kIOMasterPortDefault$constants.SEGMENT.set(kIOMasterPortDefault$constants.LAYOUT, 0L, varValue); } - public static MethodHandle IONotificationPortCreate$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$6,"IONotificationPortCreate"); + + private static class IONotificationPortCreate { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IONotificationPortCreate"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * IONotificationPortRef IONotificationPortCreate(mach_port_t mainPort); + * Function descriptor for: + * {@snippet lang=c : + * IONotificationPortRef IONotificationPortCreate(mach_port_t mainPort) + * } + */ + public static FunctionDescriptor IONotificationPortCreate$descriptor() { + return IONotificationPortCreate.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * IONotificationPortRef IONotificationPortCreate(mach_port_t mainPort) + * } + */ + public static MethodHandle IONotificationPortCreate$handle() { + return IONotificationPortCreate.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * IONotificationPortRef IONotificationPortCreate(mach_port_t mainPort) + * } + */ + public static MemorySegment IONotificationPortCreate$address() { + return IONotificationPortCreate.ADDR; + } + + /** + * {@snippet lang=c : + * IONotificationPortRef IONotificationPortCreate(mach_port_t mainPort) * } */ public static MemorySegment IONotificationPortCreate(int mainPort) { - var mh$ = IONotificationPortCreate$MH(); + var mh$ = IONotificationPortCreate.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(mainPort); + if (TRACE_DOWNCALLS) { + traceDowncall("IONotificationPortCreate", mainPort); + } + return (MemorySegment)mh$.invokeExact(mainPort); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IONotificationPortGetRunLoopSource$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$1,"IONotificationPortGetRunLoopSource"); + + private static class IONotificationPortGetRunLoopSource { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IONotificationPortGetRunLoopSource"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * CFRunLoopSourceRef IONotificationPortGetRunLoopSource(IONotificationPortRef notify); + * Function descriptor for: + * {@snippet lang=c : + * CFRunLoopSourceRef IONotificationPortGetRunLoopSource(IONotificationPortRef notify) + * } + */ + public static FunctionDescriptor IONotificationPortGetRunLoopSource$descriptor() { + return IONotificationPortGetRunLoopSource.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * CFRunLoopSourceRef IONotificationPortGetRunLoopSource(IONotificationPortRef notify) + * } + */ + public static MethodHandle IONotificationPortGetRunLoopSource$handle() { + return IONotificationPortGetRunLoopSource.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * CFRunLoopSourceRef IONotificationPortGetRunLoopSource(IONotificationPortRef notify) + * } + */ + public static MemorySegment IONotificationPortGetRunLoopSource$address() { + return IONotificationPortGetRunLoopSource.ADDR; + } + + /** + * {@snippet lang=c : + * CFRunLoopSourceRef IONotificationPortGetRunLoopSource(IONotificationPortRef notify) * } */ public static MemorySegment IONotificationPortGetRunLoopSource(MemorySegment notify) { - var mh$ = IONotificationPortGetRunLoopSource$MH(); + var mh$ = IONotificationPortGetRunLoopSource.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(notify); + if (TRACE_DOWNCALLS) { + traceDowncall("IONotificationPortGetRunLoopSource", notify); + } + return (MemorySegment)mh$.invokeExact(notify); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IOObjectRelease$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$3,"IOObjectRelease"); + + private static class IOObjectRelease { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IOObjectRelease"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * kern_return_t IOObjectRelease(io_object_t object) + * } + */ + public static FunctionDescriptor IOObjectRelease$descriptor() { + return IOObjectRelease.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * kern_return_t IOObjectRelease(io_object_t object) + * } + */ + public static MethodHandle IOObjectRelease$handle() { + return IOObjectRelease.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * kern_return_t IOObjectRelease(io_object_t object) + * } + */ + public static MemorySegment IOObjectRelease$address() { + return IOObjectRelease.ADDR; } + /** - * {@snippet : - * kern_return_t IOObjectRelease(io_object_t object); + * {@snippet lang=c : + * kern_return_t IOObjectRelease(io_object_t object) * } */ public static int IOObjectRelease(int object) { - var mh$ = IOObjectRelease$MH(); + var mh$ = IOObjectRelease.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("IOObjectRelease", object); + } return (int)mh$.invokeExact(object); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IOIteratorNext$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$4,"IOIteratorNext"); + + private static class IOIteratorNext { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IOIteratorNext"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * io_object_t IOIteratorNext(io_iterator_t iterator) + * } + */ + public static FunctionDescriptor IOIteratorNext$descriptor() { + return IOIteratorNext.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * io_object_t IOIteratorNext(io_iterator_t iterator) + * } + */ + public static MethodHandle IOIteratorNext$handle() { + return IOIteratorNext.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * io_object_t IOIteratorNext(io_iterator_t iterator) + * } + */ + public static MemorySegment IOIteratorNext$address() { + return IOIteratorNext.ADDR; } + /** - * {@snippet : - * io_object_t IOIteratorNext(io_iterator_t iterator); + * {@snippet lang=c : + * io_object_t IOIteratorNext(io_iterator_t iterator) * } */ public static int IOIteratorNext(int iterator) { - var mh$ = IOIteratorNext$MH(); + var mh$ = IOIteratorNext.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("IOIteratorNext", iterator); + } return (int)mh$.invokeExact(iterator); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IOServiceAddMatchingNotification$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$6,"IOServiceAddMatchingNotification"); + + private static class IOServiceAddMatchingNotification { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IOServiceAddMatchingNotification"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * kern_return_t IOServiceAddMatchingNotification(IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void *refCon, io_iterator_t *notification) + * } + */ + public static FunctionDescriptor IOServiceAddMatchingNotification$descriptor() { + return IOServiceAddMatchingNotification.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * kern_return_t IOServiceAddMatchingNotification(IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void *refCon, io_iterator_t *notification) + * } + */ + public static MethodHandle IOServiceAddMatchingNotification$handle() { + return IOServiceAddMatchingNotification.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * kern_return_t IOServiceAddMatchingNotification(IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void *refCon, io_iterator_t *notification) + * } + */ + public static MemorySegment IOServiceAddMatchingNotification$address() { + return IOServiceAddMatchingNotification.ADDR; } + /** - * {@snippet : - * kern_return_t IOServiceAddMatchingNotification(IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void* refCon, io_iterator_t* notification); + * {@snippet lang=c : + * kern_return_t IOServiceAddMatchingNotification(IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void *refCon, io_iterator_t *notification) * } */ public static int IOServiceAddMatchingNotification(MemorySegment notifyPort, MemorySegment notificationType, MemorySegment matching, MemorySegment callback, MemorySegment refCon, MemorySegment notification) { - var mh$ = IOServiceAddMatchingNotification$MH(); + var mh$ = IOServiceAddMatchingNotification.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("IOServiceAddMatchingNotification", notifyPort, notificationType, matching, callback, refCon, notification); + } return (int)mh$.invokeExact(notifyPort, notificationType, matching, callback, refCon, notification); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IORegistryEntryGetRegistryEntryID$MH() { - return RuntimeHelper.requireNonNull(constants$4.const$1,"IORegistryEntryGetRegistryEntryID"); + + private static class IORegistryEntryGetRegistryEntryID { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IORegistryEntryGetRegistryEntryID"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t* entryID); + * Function descriptor for: + * {@snippet lang=c : + * kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t *entryID) + * } + */ + public static FunctionDescriptor IORegistryEntryGetRegistryEntryID$descriptor() { + return IORegistryEntryGetRegistryEntryID.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t *entryID) + * } + */ + public static MethodHandle IORegistryEntryGetRegistryEntryID$handle() { + return IORegistryEntryGetRegistryEntryID.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t *entryID) + * } + */ + public static MemorySegment IORegistryEntryGetRegistryEntryID$address() { + return IORegistryEntryGetRegistryEntryID.ADDR; + } + + /** + * {@snippet lang=c : + * kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t *entryID) * } */ public static int IORegistryEntryGetRegistryEntryID(int entry, MemorySegment entryID) { - var mh$ = IORegistryEntryGetRegistryEntryID$MH(); + var mh$ = IORegistryEntryGetRegistryEntryID.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("IORegistryEntryGetRegistryEntryID", entry, entryID); + } return (int)mh$.invokeExact(entry, entryID); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IORegistryEntryCreateCFProperty$MH() { - return RuntimeHelper.requireNonNull(constants$4.const$3,"IORegistryEntryCreateCFProperty"); + + private static class IORegistryEntryCreateCFProperty { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IORegistryEntryCreateCFProperty"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) + * } + */ + public static FunctionDescriptor IORegistryEntryCreateCFProperty$descriptor() { + return IORegistryEntryCreateCFProperty.DESC; } + /** - * {@snippet : - * CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options); + * Downcall method handle for: + * {@snippet lang=c : + * CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) + * } + */ + public static MethodHandle IORegistryEntryCreateCFProperty$handle() { + return IORegistryEntryCreateCFProperty.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) + * } + */ + public static MemorySegment IORegistryEntryCreateCFProperty$address() { + return IORegistryEntryCreateCFProperty.ADDR; + } + + /** + * {@snippet lang=c : + * CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) * } */ public static MemorySegment IORegistryEntryCreateCFProperty(int entry, MemorySegment key, MemorySegment allocator, int options) { - var mh$ = IORegistryEntryCreateCFProperty$MH(); + var mh$ = IORegistryEntryCreateCFProperty.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(entry, key, allocator, options); + if (TRACE_DOWNCALLS) { + traceDowncall("IORegistryEntryCreateCFProperty", entry, key, allocator, options); + } + return (MemorySegment)mh$.invokeExact(entry, key, allocator, options); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IOServiceMatching$MH() { - return RuntimeHelper.requireNonNull(constants$4.const$4,"IOServiceMatching"); + + private static class IOServiceMatching { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IOServiceMatching"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * CFMutableDictionaryRef IOServiceMatching(const char *name) + * } + */ + public static FunctionDescriptor IOServiceMatching$descriptor() { + return IOServiceMatching.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * CFMutableDictionaryRef IOServiceMatching(const char *name) + * } + */ + public static MethodHandle IOServiceMatching$handle() { + return IOServiceMatching.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * CFMutableDictionaryRef IOServiceMatching(const char *name) + * } + */ + public static MemorySegment IOServiceMatching$address() { + return IOServiceMatching.ADDR; } + /** - * {@snippet : - * CFMutableDictionaryRef IOServiceMatching(char* name); + * {@snippet lang=c : + * CFMutableDictionaryRef IOServiceMatching(const char *name) * } */ public static MemorySegment IOServiceMatching(MemorySegment name) { - var mh$ = IOServiceMatching$MH(); + var mh$ = IOServiceMatching.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(name); + if (TRACE_DOWNCALLS) { + traceDowncall("IOServiceMatching", name); + } + return (MemorySegment)mh$.invokeExact(name); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - public static MethodHandle IOCreatePlugInInterfaceForService$MH() { - return RuntimeHelper.requireNonNull(constants$43.const$5,"IOCreatePlugInInterfaceForService"); + + private static class IOCreatePlugInInterfaceForService { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("IOCreatePlugInInterfaceForService"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + /** - * {@snippet : - * kern_return_t IOCreatePlugInInterfaceForService(io_service_t service, CFUUIDRef pluginType, CFUUIDRef interfaceType, IOCFPlugInInterface*** theInterface, SInt32* theScore); + * Function descriptor for: + * {@snippet lang=c : + * kern_return_t IOCreatePlugInInterfaceForService(io_service_t service, CFUUIDRef pluginType, CFUUIDRef interfaceType, IOCFPlugInInterface ***theInterface, SInt32 *theScore) + * } + */ + public static FunctionDescriptor IOCreatePlugInInterfaceForService$descriptor() { + return IOCreatePlugInInterfaceForService.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * kern_return_t IOCreatePlugInInterfaceForService(io_service_t service, CFUUIDRef pluginType, CFUUIDRef interfaceType, IOCFPlugInInterface ***theInterface, SInt32 *theScore) + * } + */ + public static MethodHandle IOCreatePlugInInterfaceForService$handle() { + return IOCreatePlugInInterfaceForService.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * kern_return_t IOCreatePlugInInterfaceForService(io_service_t service, CFUUIDRef pluginType, CFUUIDRef interfaceType, IOCFPlugInInterface ***theInterface, SInt32 *theScore) + * } + */ + public static MemorySegment IOCreatePlugInInterfaceForService$address() { + return IOCreatePlugInInterfaceForService.ADDR; + } + + /** + * {@snippet lang=c : + * kern_return_t IOCreatePlugInInterfaceForService(io_service_t service, CFUUIDRef pluginType, CFUUIDRef interfaceType, IOCFPlugInInterface ***theInterface, SInt32 *theScore) * } */ public static int IOCreatePlugInInterfaceForService(int service, MemorySegment pluginType, MemorySegment interfaceType, MemorySegment theInterface, MemorySegment theScore) { - var mh$ = IOCreatePlugInInterfaceForService$MH(); + var mh$ = IOCreatePlugInInterfaceForService.HANDLE; try { + if (TRACE_DOWNCALLS) { + traceDowncall("IOCreatePlugInInterfaceForService", service, pluginType, interfaceType, theInterface, theScore); + } return (int)mh$.invokeExact(service, pluginType, interfaceType, theInterface, theScore); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } + private static final int kIOReturnExclusiveAccess = (int)-536870203L; /** - * {@snippet : + * {@snippet lang=c : * #define kIOReturnExclusiveAccess -536870203 * } */ public static int kIOReturnExclusiveAccess() { - return (int)-536870203L; + return kIOReturnExclusiveAccess; } + private static final int kIOReturnAborted = (int)-536870165L; /** - * {@snippet : + * {@snippet lang=c : * #define kIOReturnAborted -536870165 * } */ public static int kIOReturnAborted() { - return (int)-536870165L; + return kIOReturnAborted; } + private static final int kIOUSBPipeStalled = (int)-536854449L; /** - * {@snippet : + * {@snippet lang=c : * #define kIOUSBPipeStalled -536854449 * } */ public static int kIOUSBPipeStalled() { - return (int)-536854449L; + return kIOUSBPipeStalled; } + private static final int kIOUSBTransactionTimeout = (int)-536854447L; /** - * {@snippet : + * {@snippet lang=c : * #define kIOUSBTransactionTimeout -536854447 * } */ public static int kIOUSBTransactionTimeout() { - return (int)-536854447L; + return kIOUSBTransactionTimeout; } /** - * {@snippet : + * {@snippet lang=c : * #define kIOFirstMatchNotification "IOServiceFirstMatch" * } */ public static MemorySegment kIOFirstMatchNotification() { - return constants$44.const$0; + class Holder { + static final MemorySegment kIOFirstMatchNotification + = IOKit.LIBRARY_ARENA.allocateFrom("IOServiceFirstMatch"); + } + return Holder.kIOFirstMatchNotification; } /** - * {@snippet : + * {@snippet lang=c : * #define kIOTerminatedNotification "IOServiceTerminate" * } */ public static MemorySegment kIOTerminatedNotification() { - return constants$44.const$1; + class Holder { + static final MemorySegment kIOTerminatedNotification + = IOKit.LIBRARY_ARENA.allocateFrom("IOServiceTerminate"); + } + return Holder.kIOTerminatedNotification; } /** - * {@snippet : + * {@snippet lang=c : * #define kIOUSBDeviceClassName "IOUSBDevice" * } */ public static MemorySegment kIOUSBDeviceClassName() { - return constants$44.const$2; + class Holder { + static final MemorySegment kIOUSBDeviceClassName + = IOKit.LIBRARY_ARENA.allocateFrom("IOUSBDevice"); + } + return Holder.kIOUSBDeviceClassName; } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOServiceAddMatchingNotification$callback.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOServiceAddMatchingNotification$callback.java new file mode 100644 index 00000000..87fa4df1 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOServiceAddMatchingNotification$callback.java @@ -0,0 +1,70 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.iokit; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +/** + * {@snippet lang=c : + * IOServiceMatchingCallback callback + * } + */ +public final class IOServiceAddMatchingNotification$callback { + + private IOServiceAddMatchingNotification$callback() { + // Should not be called directly + } + + /** + * The function pointer signature, expressed as a functional interface + */ + public interface Function { + void apply(MemorySegment _x0, int _x1); + } + + private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid( + IOKit.C_POINTER, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + private static final MethodHandle UP$MH = IOKit.upcallHandle(IOServiceAddMatchingNotification$callback.Function.class, "apply", $DESC); + + /** + * Allocates a new upcall stub, whose implementation is defined by {@code fi}. + * The lifetime of the returned segment is managed by {@code arena} + */ + public static MemorySegment allocate(IOServiceAddMatchingNotification$callback.Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, arena); + } + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static void invoke(MemorySegment funcPtr, MemorySegment _x0, int _x1) { + try { + DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDevRequest.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDevRequest.java index ae3953ce..0f65940c 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDevRequest.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDevRequest.java @@ -2,224 +2,403 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct { * UInt8 bmRequestType; * UInt8 bRequest; * UInt16 wValue; * UInt16 wIndex; * UInt16 wLength; - * void* pData; + * void *pData; * UInt32 wLenDone; - * }; + * } * } */ public class IOUSBDevRequest { - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; + IOUSBDevRequest() { + // Should not be called directly + } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_CHAR.withName("bmRequestType"), + IOKit.C_CHAR.withName("bRequest"), + IOKit.C_SHORT.withName("wValue"), + IOKit.C_SHORT.withName("wIndex"), + IOKit.C_SHORT.withName("wLength"), + IOKit.C_POINTER.withName("pData"), + IOKit.C_INT.withName("wLenDone"), + MemoryLayout.paddingLayout(4) + ).withName("IOUSBDevRequest"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } - public static VarHandle bmRequestType$VH() { - return constants$0.const$1; + + private static final OfByte bmRequestType$LAYOUT = (OfByte)$LAYOUT.select(groupElement("bmRequestType")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 bmRequestType + * } + */ + public static final OfByte bmRequestType$layout() { + return bmRequestType$LAYOUT; + } + + private static final long bmRequestType$OFFSET = $LAYOUT.byteOffset(groupElement("bmRequestType")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 bmRequestType + * } + */ + public static final long bmRequestType$offset() { + return bmRequestType$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 bmRequestType; + * {@snippet lang=c : + * UInt8 bmRequestType * } */ - public static byte bmRequestType$get(MemorySegment seg) { - return (byte)constants$0.const$1.get(seg); + public static byte bmRequestType(MemorySegment struct) { + return struct.get(bmRequestType$LAYOUT, bmRequestType$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 bmRequestType; + * {@snippet lang=c : + * UInt8 bmRequestType * } */ - public static void bmRequestType$set(MemorySegment seg, byte x) { - constants$0.const$1.set(seg, x); + public static void bmRequestType(MemorySegment struct, byte fieldValue) { + struct.set(bmRequestType$LAYOUT, bmRequestType$OFFSET, fieldValue); } - public static byte bmRequestType$get(MemorySegment seg, long index) { - return (byte)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void bmRequestType$set(MemorySegment seg, long index, byte x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); + + private static final OfByte bRequest$LAYOUT = (OfByte)$LAYOUT.select(groupElement("bRequest")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt8 bRequest + * } + */ + public static final OfByte bRequest$layout() { + return bRequest$LAYOUT; } - public static VarHandle bRequest$VH() { - return constants$0.const$2; + + private static final long bRequest$OFFSET = $LAYOUT.byteOffset(groupElement("bRequest")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt8 bRequest + * } + */ + public static final long bRequest$offset() { + return bRequest$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt8 bRequest; + * {@snippet lang=c : + * UInt8 bRequest * } */ - public static byte bRequest$get(MemorySegment seg) { - return (byte)constants$0.const$2.get(seg); + public static byte bRequest(MemorySegment struct) { + return struct.get(bRequest$LAYOUT, bRequest$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt8 bRequest; + * {@snippet lang=c : + * UInt8 bRequest * } */ - public static void bRequest$set(MemorySegment seg, byte x) { - constants$0.const$2.set(seg, x); + public static void bRequest(MemorySegment struct, byte fieldValue) { + struct.set(bRequest$LAYOUT, bRequest$OFFSET, fieldValue); } - public static byte bRequest$get(MemorySegment seg, long index) { - return (byte)constants$0.const$2.get(seg.asSlice(index*sizeof())); - } - public static void bRequest$set(MemorySegment seg, long index, byte x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wValue$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wValue")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 wValue + * } + */ + public static final OfShort wValue$layout() { + return wValue$LAYOUT; } - public static VarHandle wValue$VH() { - return constants$0.const$3; + + private static final long wValue$OFFSET = $LAYOUT.byteOffset(groupElement("wValue")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 wValue + * } + */ + public static final long wValue$offset() { + return wValue$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 wValue; + * {@snippet lang=c : + * UInt16 wValue * } */ - public static short wValue$get(MemorySegment seg) { - return (short)constants$0.const$3.get(seg); + public static short wValue(MemorySegment struct) { + return struct.get(wValue$LAYOUT, wValue$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 wValue; + * {@snippet lang=c : + * UInt16 wValue * } */ - public static void wValue$set(MemorySegment seg, short x) { - constants$0.const$3.set(seg, x); + public static void wValue(MemorySegment struct, short fieldValue) { + struct.set(wValue$LAYOUT, wValue$OFFSET, fieldValue); } - public static short wValue$get(MemorySegment seg, long index) { - return (short)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void wValue$set(MemorySegment seg, long index, short x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wIndex$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wIndex")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 wIndex + * } + */ + public static final OfShort wIndex$layout() { + return wIndex$LAYOUT; } - public static VarHandle wIndex$VH() { - return constants$0.const$4; + + private static final long wIndex$OFFSET = $LAYOUT.byteOffset(groupElement("wIndex")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 wIndex + * } + */ + public static final long wIndex$offset() { + return wIndex$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 wIndex; + * {@snippet lang=c : + * UInt16 wIndex * } */ - public static short wIndex$get(MemorySegment seg) { - return (short)constants$0.const$4.get(seg); + public static short wIndex(MemorySegment struct) { + return struct.get(wIndex$LAYOUT, wIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 wIndex; + * {@snippet lang=c : + * UInt16 wIndex * } */ - public static void wIndex$set(MemorySegment seg, short x) { - constants$0.const$4.set(seg, x); + public static void wIndex(MemorySegment struct, short fieldValue) { + struct.set(wIndex$LAYOUT, wIndex$OFFSET, fieldValue); } - public static short wIndex$get(MemorySegment seg, long index) { - return (short)constants$0.const$4.get(seg.asSlice(index*sizeof())); - } - public static void wIndex$set(MemorySegment seg, long index, short x) { - constants$0.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort wLength$LAYOUT = (OfShort)$LAYOUT.select(groupElement("wLength")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 wLength + * } + */ + public static final OfShort wLength$layout() { + return wLength$LAYOUT; } - public static VarHandle wLength$VH() { - return constants$0.const$5; + + private static final long wLength$OFFSET = $LAYOUT.byteOffset(groupElement("wLength")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 wLength + * } + */ + public static final long wLength$offset() { + return wLength$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 wLength; + * {@snippet lang=c : + * UInt16 wLength * } */ - public static short wLength$get(MemorySegment seg) { - return (short)constants$0.const$5.get(seg); + public static short wLength(MemorySegment struct) { + return struct.get(wLength$LAYOUT, wLength$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 wLength; + * {@snippet lang=c : + * UInt16 wLength * } */ - public static void wLength$set(MemorySegment seg, short x) { - constants$0.const$5.set(seg, x); - } - public static short wLength$get(MemorySegment seg, long index) { - return (short)constants$0.const$5.get(seg.asSlice(index*sizeof())); + public static void wLength(MemorySegment struct, short fieldValue) { + struct.set(wLength$LAYOUT, wLength$OFFSET, fieldValue); } - public static void wLength$set(MemorySegment seg, long index, short x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final AddressLayout pData$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("pData")); + + /** + * Layout for field: + * {@snippet lang=c : + * void *pData + * } + */ + public static final AddressLayout pData$layout() { + return pData$LAYOUT; } - public static VarHandle pData$VH() { - return constants$1.const$0; + + private static final long pData$OFFSET = $LAYOUT.byteOffset(groupElement("pData")); + + /** + * Offset for field: + * {@snippet lang=c : + * void *pData + * } + */ + public static final long pData$offset() { + return pData$OFFSET; } + /** * Getter for field: - * {@snippet : - * void* pData; + * {@snippet lang=c : + * void *pData * } */ - public static MemorySegment pData$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$0.get(seg); + public static MemorySegment pData(MemorySegment struct) { + return struct.get(pData$LAYOUT, pData$OFFSET); } + /** * Setter for field: - * {@snippet : - * void* pData; + * {@snippet lang=c : + * void *pData * } */ - public static void pData$set(MemorySegment seg, MemorySegment x) { - constants$1.const$0.set(seg, x); - } - public static MemorySegment pData$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$0.get(seg.asSlice(index*sizeof())); + public static void pData(MemorySegment struct, MemorySegment fieldValue) { + struct.set(pData$LAYOUT, pData$OFFSET, fieldValue); } - public static void pData$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$0.set(seg.asSlice(index*sizeof()), x); + + private static final OfInt wLenDone$LAYOUT = (OfInt)$LAYOUT.select(groupElement("wLenDone")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt32 wLenDone + * } + */ + public static final OfInt wLenDone$layout() { + return wLenDone$LAYOUT; } - public static VarHandle wLenDone$VH() { - return constants$1.const$1; + + private static final long wLenDone$OFFSET = $LAYOUT.byteOffset(groupElement("wLenDone")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt32 wLenDone + * } + */ + public static final long wLenDone$offset() { + return wLenDone$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt32 wLenDone; + * {@snippet lang=c : + * UInt32 wLenDone * } */ - public static int wLenDone$get(MemorySegment seg) { - return (int)constants$1.const$1.get(seg); + public static int wLenDone(MemorySegment struct) { + return struct.get(wLenDone$LAYOUT, wLenDone$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt32 wLenDone; + * {@snippet lang=c : + * UInt32 wLenDone * } */ - public static void wLenDone$set(MemorySegment seg, int x) { - constants$1.const$1.set(seg, x); + public static void wLenDone(MemorySegment struct, int fieldValue) { + struct.set(wLenDone$LAYOUT, wLenDone$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static int wLenDone$get(MemorySegment seg, long index) { - return (int)constants$1.const$1.get(seg.asSlice(index*sizeof())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static void wLenDone$set(MemorySegment seg, long index, int x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceInterface187.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceInterface187.java deleted file mode 100644 index be0be089..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceInterface187.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -/** - * {@snippet : - * typedef struct IOUSBDeviceStruct187 IOUSBDeviceInterface187; - * } - */ -public final class IOUSBDeviceInterface187 extends IOUSBDeviceStruct187 { - - // Suppresses default constructor, ensuring non-instantiability. - private IOUSBDeviceInterface187() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceStruct187.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceStruct187.java index ad8d79c2..db64afe0 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceStruct187.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBDeviceStruct187.java @@ -2,2054 +2,3455 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct IOUSBDeviceStruct187 { - * void* _reserved; - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); - * ULONG (*AddRef)(void*); - * ULONG (*Release)(void*); - * IOReturn (*CreateDeviceAsyncEventSource)(void*,CFRunLoopSourceRef*); - * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void*); - * IOReturn (*CreateDeviceAsyncPort)(void*,mach_port_t*); - * mach_port_t (*GetDeviceAsyncPort)(void*); - * IOReturn (*USBDeviceOpen)(void*); - * IOReturn (*USBDeviceClose)(void*); - * IOReturn (*GetDeviceClass)(void*,UInt8*); - * IOReturn (*GetDeviceSubClass)(void*,UInt8*); - * IOReturn (*GetDeviceProtocol)(void*,UInt8*); - * IOReturn (*GetDeviceVendor)(void*,UInt16*); - * IOReturn (*GetDeviceProduct)(void*,UInt16*); - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); - * IOReturn (*GetDeviceAddress)(void*,USBDeviceAddress*); - * IOReturn (*GetDeviceBusPowerAvailable)(void*,UInt32*); - * IOReturn (*GetDeviceSpeed)(void*,UInt8*); - * IOReturn (*GetNumberOfConfigurations)(void*,UInt8*); - * IOReturn (*GetLocationID)(void*,UInt32*); - * IOReturn (*GetConfigurationDescriptorPtr)(void*,UInt8,IOUSBConfigurationDescriptorPtr*); - * IOReturn (*GetConfiguration)(void*,UInt8*); - * IOReturn (*SetConfiguration)(void*,UInt8); - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); - * IOReturn (*ResetDevice)(void*); - * IOReturn (*DeviceRequest)(void*,IOUSBDevRequest*); - * IOReturn (*DeviceRequestAsync)(void*,IOUSBDevRequest*,IOAsyncCallback1,void*); - * IOReturn (*CreateInterfaceIterator)(void*,IOUSBFindInterfaceRequest*,io_iterator_t*); - * IOReturn (*USBDeviceOpenSeize)(void*); - * IOReturn (*DeviceRequestTO)(void*,IOUSBDevRequestTO*); - * IOReturn (*DeviceRequestAsyncTO)(void*,IOUSBDevRequestTO*,IOAsyncCallback1,void*); - * IOReturn (*USBDeviceSuspend)(void*,Boolean); - * IOReturn (*USBDeviceAbortPipeZero)(void*); - * IOReturn (*USBGetManufacturerStringIndex)(void*,UInt8*); - * IOReturn (*USBGetProductStringIndex)(void*,UInt8*); - * IOReturn (*USBGetSerialNumberStringIndex)(void*,UInt8*); - * IOReturn (*USBDeviceReEnumerate)(void*,UInt32); - * }; + * void *_reserved; + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *); + * ULONG (*AddRef)(void *); + * ULONG (*Release)(void *); + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *); + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *); + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *); + * mach_port_t (*GetDeviceAsyncPort)(void *); + * IOReturn (*USBDeviceOpen)(void *); + * IOReturn (*USBDeviceClose)(void *); + * IOReturn (*GetDeviceClass)(void *, UInt8 *); + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *); + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *); + * IOReturn (*GetDeviceVendor)(void *, UInt16 *); + * IOReturn (*GetDeviceProduct)(void *, UInt16 *); + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *); + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *); + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *); + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *); + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *); + * IOReturn (*GetLocationID)(void *, UInt32 *); + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *); + * IOReturn (*GetConfiguration)(void *, UInt8 *); + * IOReturn (*SetConfiguration)(void *, UInt8); + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *); + * IOReturn (*ResetDevice)(void *); + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *); + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *); + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *); + * IOReturn (*USBDeviceOpenSeize)(void *); + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *); + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *); + * IOReturn (*USBDeviceSuspend)(void *, Boolean); + * IOReturn (*USBDeviceAbortPipeZero)(void *); + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *); + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *); + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *); + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32); + * } * } */ public class IOUSBDeviceStruct187 { - public static MemoryLayout $LAYOUT() { - return constants$4.const$5; - } - public static VarHandle _reserved$VH() { - return constants$5.const$0; + IOUSBDeviceStruct187() { + // Should not be called directly } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_POINTER.withName("_reserved"), + IOKit.C_POINTER.withName("QueryInterface"), + IOKit.C_POINTER.withName("AddRef"), + IOKit.C_POINTER.withName("Release"), + IOKit.C_POINTER.withName("CreateDeviceAsyncEventSource"), + IOKit.C_POINTER.withName("GetDeviceAsyncEventSource"), + IOKit.C_POINTER.withName("CreateDeviceAsyncPort"), + IOKit.C_POINTER.withName("GetDeviceAsyncPort"), + IOKit.C_POINTER.withName("USBDeviceOpen"), + IOKit.C_POINTER.withName("USBDeviceClose"), + IOKit.C_POINTER.withName("GetDeviceClass"), + IOKit.C_POINTER.withName("GetDeviceSubClass"), + IOKit.C_POINTER.withName("GetDeviceProtocol"), + IOKit.C_POINTER.withName("GetDeviceVendor"), + IOKit.C_POINTER.withName("GetDeviceProduct"), + IOKit.C_POINTER.withName("GetDeviceReleaseNumber"), + IOKit.C_POINTER.withName("GetDeviceAddress"), + IOKit.C_POINTER.withName("GetDeviceBusPowerAvailable"), + IOKit.C_POINTER.withName("GetDeviceSpeed"), + IOKit.C_POINTER.withName("GetNumberOfConfigurations"), + IOKit.C_POINTER.withName("GetLocationID"), + IOKit.C_POINTER.withName("GetConfigurationDescriptorPtr"), + IOKit.C_POINTER.withName("GetConfiguration"), + IOKit.C_POINTER.withName("SetConfiguration"), + IOKit.C_POINTER.withName("GetBusFrameNumber"), + IOKit.C_POINTER.withName("ResetDevice"), + IOKit.C_POINTER.withName("DeviceRequest"), + IOKit.C_POINTER.withName("DeviceRequestAsync"), + IOKit.C_POINTER.withName("CreateInterfaceIterator"), + IOKit.C_POINTER.withName("USBDeviceOpenSeize"), + IOKit.C_POINTER.withName("DeviceRequestTO"), + IOKit.C_POINTER.withName("DeviceRequestAsyncTO"), + IOKit.C_POINTER.withName("USBDeviceSuspend"), + IOKit.C_POINTER.withName("USBDeviceAbortPipeZero"), + IOKit.C_POINTER.withName("USBGetManufacturerStringIndex"), + IOKit.C_POINTER.withName("USBGetProductStringIndex"), + IOKit.C_POINTER.withName("USBGetSerialNumberStringIndex"), + IOKit.C_POINTER.withName("USBDeviceReEnumerate") + ).withName("IOUSBDeviceStruct187"); + /** - * Getter for field: - * {@snippet : - * void* _reserved; - * } + * The layout of this struct */ - public static MemorySegment _reserved$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$5.const$0.get(seg); + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final AddressLayout _reserved$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("_reserved")); + /** - * Setter for field: - * {@snippet : - * void* _reserved; + * Layout for field: + * {@snippet lang=c : + * void *_reserved * } */ - public static void _reserved$set(MemorySegment seg, MemorySegment x) { - constants$5.const$0.set(seg, x); - } - public static MemorySegment _reserved$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$5.const$0.get(seg.asSlice(index*sizeof())); - } - public static void _reserved$set(MemorySegment seg, long index, MemorySegment x) { - constants$5.const$0.set(seg.asSlice(index*sizeof()), x); + public static final AddressLayout _reserved$layout() { + return _reserved$LAYOUT; } + + private static final long _reserved$OFFSET = $LAYOUT.byteOffset(groupElement("_reserved")); + /** - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * Offset for field: + * {@snippet lang=c : + * void *_reserved * } */ - public interface QueryInterface { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(QueryInterface fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$5.const$2, fi, constants$5.const$1, scope); - } - static QueryInterface ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$5.const$3.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long _reserved$offset() { + return _reserved$OFFSET; } - public static VarHandle QueryInterface$VH() { - return constants$5.const$4; - } /** * Getter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * void *_reserved * } */ - public static MemorySegment QueryInterface$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$5.const$4.get(seg); + public static MemorySegment _reserved(MemorySegment struct) { + return struct.get(_reserved$LAYOUT, _reserved$OFFSET); } + /** * Setter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * void *_reserved * } */ - public static void QueryInterface$set(MemorySegment seg, MemorySegment x) { - constants$5.const$4.set(seg, x); - } - public static MemorySegment QueryInterface$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$5.const$4.get(seg.asSlice(index*sizeof())); - } - public static void QueryInterface$set(MemorySegment seg, long index, MemorySegment x) { - constants$5.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static QueryInterface QueryInterface(MemorySegment segment, Arena scope) { - return QueryInterface.ofAddress(QueryInterface$get(segment), scope); + public static void _reserved(MemorySegment struct, MemorySegment fieldValue) { + struct.set(_reserved$LAYOUT, _reserved$OFFSET, fieldValue); } + /** - * {@snippet : - * ULONG (*AddRef)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public interface AddRef { + public final static class QueryInterface { - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(AddRef fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$6.const$0, fi, constants$5.const$5, scope); + private QueryInterface() { + // Should not be called directly } - static AddRef ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + CFUUIDBytes.layout(), + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle AddRef$VH() { - return constants$6.const$2; - } - /** - * Getter for field: - * {@snippet : - * ULONG (*AddRef)(void*); - * } - */ - public static MemorySegment AddRef$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$6.const$2.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout QueryInterface$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("QueryInterface")); + /** - * Setter for field: - * {@snippet : - * ULONG (*AddRef)(void*); + * Layout for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static void AddRef$set(MemorySegment seg, MemorySegment x) { - constants$6.const$2.set(seg, x); - } - public static MemorySegment AddRef$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$6.const$2.get(seg.asSlice(index*sizeof())); - } - public static void AddRef$set(MemorySegment seg, long index, MemorySegment x) { - constants$6.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static AddRef AddRef(MemorySegment segment, Arena scope) { - return AddRef.ofAddress(AddRef$get(segment), scope); + public static final AddressLayout QueryInterface$layout() { + return QueryInterface$LAYOUT; } + + private static final long QueryInterface$OFFSET = $LAYOUT.byteOffset(groupElement("QueryInterface")); + /** - * {@snippet : - * ULONG (*Release)(void*); + * Offset for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public interface Release { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(Release fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$6.const$3, fi, constants$5.const$5, scope); - } - static Release ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long QueryInterface$offset() { + return QueryInterface$OFFSET; } - public static VarHandle Release$VH() { - return constants$6.const$4; - } /** * Getter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static MemorySegment Release$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$6.const$4.get(seg); + public static MemorySegment QueryInterface(MemorySegment struct) { + return struct.get(QueryInterface$LAYOUT, QueryInterface$OFFSET); } + /** * Setter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static void Release$set(MemorySegment seg, MemorySegment x) { - constants$6.const$4.set(seg, x); - } - public static MemorySegment Release$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$6.const$4.get(seg.asSlice(index*sizeof())); - } - public static void Release$set(MemorySegment seg, long index, MemorySegment x) { - constants$6.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static Release Release(MemorySegment segment, Arena scope) { - return Release.ofAddress(Release$get(segment), scope); + public static void QueryInterface(MemorySegment struct, MemorySegment fieldValue) { + struct.set(QueryInterface$LAYOUT, QueryInterface$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*CreateDeviceAsyncEventSource)(void*,CFRunLoopSourceRef*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public interface CreateDeviceAsyncEventSource { + public final static class AddRef { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(CreateDeviceAsyncEventSource fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$7.const$0, fi, constants$6.const$5, scope); + private AddRef() { + // Should not be called directly } - static CreateDeviceAsyncEventSource ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle CreateDeviceAsyncEventSource$VH() { - return constants$7.const$2; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*CreateDeviceAsyncEventSource)(void*,CFRunLoopSourceRef*); - * } - */ - public static MemorySegment CreateDeviceAsyncEventSource$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$7.const$2.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout AddRef$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("AddRef")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*CreateDeviceAsyncEventSource)(void*,CFRunLoopSourceRef*); + * Layout for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static void CreateDeviceAsyncEventSource$set(MemorySegment seg, MemorySegment x) { - constants$7.const$2.set(seg, x); - } - public static MemorySegment CreateDeviceAsyncEventSource$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$7.const$2.get(seg.asSlice(index*sizeof())); - } - public static void CreateDeviceAsyncEventSource$set(MemorySegment seg, long index, MemorySegment x) { - constants$7.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static CreateDeviceAsyncEventSource CreateDeviceAsyncEventSource(MemorySegment segment, Arena scope) { - return CreateDeviceAsyncEventSource.ofAddress(CreateDeviceAsyncEventSource$get(segment), scope); + public static final AddressLayout AddRef$layout() { + return AddRef$LAYOUT; } + + private static final long AddRef$OFFSET = $LAYOUT.byteOffset(groupElement("AddRef")); + /** - * {@snippet : - * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void*); + * Offset for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public interface GetDeviceAsyncEventSource { - - java.lang.foreign.MemorySegment apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(GetDeviceAsyncEventSource fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$7.const$3, fi, constants$3.const$0, scope); - } - static GetDeviceAsyncEventSource ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (java.lang.foreign.MemorySegment)constants$7.const$4.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long AddRef$offset() { + return AddRef$OFFSET; } - public static VarHandle GetDeviceAsyncEventSource$VH() { - return constants$7.const$5; - } /** * Getter for field: - * {@snippet : - * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static MemorySegment GetDeviceAsyncEventSource$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$7.const$5.get(seg); + public static MemorySegment AddRef(MemorySegment struct) { + return struct.get(AddRef$LAYOUT, AddRef$OFFSET); } + /** * Setter for field: - * {@snippet : - * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static void GetDeviceAsyncEventSource$set(MemorySegment seg, MemorySegment x) { - constants$7.const$5.set(seg, x); - } - public static MemorySegment GetDeviceAsyncEventSource$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$7.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceAsyncEventSource$set(MemorySegment seg, long index, MemorySegment x) { - constants$7.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceAsyncEventSource GetDeviceAsyncEventSource(MemorySegment segment, Arena scope) { - return GetDeviceAsyncEventSource.ofAddress(GetDeviceAsyncEventSource$get(segment), scope); + public static void AddRef(MemorySegment struct, MemorySegment fieldValue) { + struct.set(AddRef$LAYOUT, AddRef$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*CreateDeviceAsyncPort)(void*,mach_port_t*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public interface CreateDeviceAsyncPort { + public final static class Release { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(CreateDeviceAsyncPort fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$8.const$0, fi, constants$6.const$5, scope); + private Release() { + // Should not be called directly } - static CreateDeviceAsyncPort ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle CreateDeviceAsyncPort$VH() { - return constants$8.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*CreateDeviceAsyncPort)(void*,mach_port_t*); - * } - */ - public static MemorySegment CreateDeviceAsyncPort$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$8.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout Release$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Release")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*CreateDeviceAsyncPort)(void*,mach_port_t*); + * Layout for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static void CreateDeviceAsyncPort$set(MemorySegment seg, MemorySegment x) { - constants$8.const$1.set(seg, x); - } - public static MemorySegment CreateDeviceAsyncPort$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$8.const$1.get(seg.asSlice(index*sizeof())); - } - public static void CreateDeviceAsyncPort$set(MemorySegment seg, long index, MemorySegment x) { - constants$8.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static CreateDeviceAsyncPort CreateDeviceAsyncPort(MemorySegment segment, Arena scope) { - return CreateDeviceAsyncPort.ofAddress(CreateDeviceAsyncPort$get(segment), scope); + public static final AddressLayout Release$layout() { + return Release$LAYOUT; } + + private static final long Release$OFFSET = $LAYOUT.byteOffset(groupElement("Release")); + /** - * {@snippet : - * mach_port_t (*GetDeviceAsyncPort)(void*); + * Offset for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public interface GetDeviceAsyncPort { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(GetDeviceAsyncPort fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$8.const$2, fi, constants$5.const$5, scope); - } - static GetDeviceAsyncPort ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long Release$offset() { + return Release$OFFSET; } - public static VarHandle GetDeviceAsyncPort$VH() { - return constants$8.const$3; - } /** * Getter for field: - * {@snippet : - * mach_port_t (*GetDeviceAsyncPort)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static MemorySegment GetDeviceAsyncPort$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$8.const$3.get(seg); + public static MemorySegment Release(MemorySegment struct) { + return struct.get(Release$LAYOUT, Release$OFFSET); } + /** * Setter for field: - * {@snippet : - * mach_port_t (*GetDeviceAsyncPort)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static void GetDeviceAsyncPort$set(MemorySegment seg, MemorySegment x) { - constants$8.const$3.set(seg, x); - } - public static MemorySegment GetDeviceAsyncPort$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$8.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceAsyncPort$set(MemorySegment seg, long index, MemorySegment x) { - constants$8.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceAsyncPort GetDeviceAsyncPort(MemorySegment segment, Arena scope) { - return GetDeviceAsyncPort.ofAddress(GetDeviceAsyncPort$get(segment), scope); + public static void Release(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Release$LAYOUT, Release$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBDeviceOpen)(void*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public interface USBDeviceOpen { + public final static class CreateDeviceAsyncEventSource { + + private CreateDeviceAsyncEventSource() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBDeviceOpen fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$8.const$4, fi, constants$5.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static USBDeviceOpen ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle USBDeviceOpen$VH() { - return constants$8.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceOpen)(void*); - * } - */ - public static MemorySegment USBDeviceOpen$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$8.const$5.get(seg); - } + private static final AddressLayout CreateDeviceAsyncEventSource$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("CreateDeviceAsyncEventSource")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceOpen)(void*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static void USBDeviceOpen$set(MemorySegment seg, MemorySegment x) { - constants$8.const$5.set(seg, x); - } - public static MemorySegment USBDeviceOpen$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$8.const$5.get(seg.asSlice(index*sizeof())); - } - public static void USBDeviceOpen$set(MemorySegment seg, long index, MemorySegment x) { - constants$8.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static USBDeviceOpen USBDeviceOpen(MemorySegment segment, Arena scope) { - return USBDeviceOpen.ofAddress(USBDeviceOpen$get(segment), scope); + public static final AddressLayout CreateDeviceAsyncEventSource$layout() { + return CreateDeviceAsyncEventSource$LAYOUT; } + + private static final long CreateDeviceAsyncEventSource$OFFSET = $LAYOUT.byteOffset(groupElement("CreateDeviceAsyncEventSource")); + /** - * {@snippet : - * IOReturn (*USBDeviceClose)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public interface USBDeviceClose { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBDeviceClose fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$9.const$0, fi, constants$5.const$5, scope); - } - static USBDeviceClose ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long CreateDeviceAsyncEventSource$offset() { + return CreateDeviceAsyncEventSource$OFFSET; } - public static VarHandle USBDeviceClose$VH() { - return constants$9.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceClose)(void*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static MemorySegment USBDeviceClose$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$9.const$1.get(seg); + public static MemorySegment CreateDeviceAsyncEventSource(MemorySegment struct) { + return struct.get(CreateDeviceAsyncEventSource$LAYOUT, CreateDeviceAsyncEventSource$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceClose)(void*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static void USBDeviceClose$set(MemorySegment seg, MemorySegment x) { - constants$9.const$1.set(seg, x); - } - public static MemorySegment USBDeviceClose$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$9.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBDeviceClose$set(MemorySegment seg, long index, MemorySegment x) { - constants$9.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBDeviceClose USBDeviceClose(MemorySegment segment, Arena scope) { - return USBDeviceClose.ofAddress(USBDeviceClose$get(segment), scope); + public static void CreateDeviceAsyncEventSource(MemorySegment struct, MemorySegment fieldValue) { + struct.set(CreateDeviceAsyncEventSource$LAYOUT, CreateDeviceAsyncEventSource$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *) * } */ - public interface GetDeviceClass { + public final static class GetDeviceAsyncEventSource { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceClass fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$9.const$2, fi, constants$6.const$5, scope); + private GetDeviceAsyncEventSource() { + // Should not be called directly } - static GetDeviceClass ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDeviceClass$VH() { - return constants$9.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceClass)(void*,UInt8*); - * } - */ - public static MemorySegment GetDeviceClass$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$9.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static MemorySegment invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (MemorySegment) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout GetDeviceAsyncEventSource$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceAsyncEventSource")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceClass)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *) * } */ - public static void GetDeviceClass$set(MemorySegment seg, MemorySegment x) { - constants$9.const$3.set(seg, x); - } - public static MemorySegment GetDeviceClass$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$9.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceClass$set(MemorySegment seg, long index, MemorySegment x) { - constants$9.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceClass GetDeviceClass(MemorySegment segment, Arena scope) { - return GetDeviceClass.ofAddress(GetDeviceClass$get(segment), scope); + public static final AddressLayout GetDeviceAsyncEventSource$layout() { + return GetDeviceAsyncEventSource$LAYOUT; } + + private static final long GetDeviceAsyncEventSource$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceAsyncEventSource")); + /** - * {@snippet : - * IOReturn (*GetDeviceSubClass)(void*,UInt8*); + * Offset for field: + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *) * } */ - public interface GetDeviceSubClass { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceSubClass fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$9.const$4, fi, constants$6.const$5, scope); - } - static GetDeviceSubClass ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long GetDeviceAsyncEventSource$offset() { + return GetDeviceAsyncEventSource$OFFSET; } - public static VarHandle GetDeviceSubClass$VH() { - return constants$9.const$5; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceSubClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *) * } */ - public static MemorySegment GetDeviceSubClass$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$9.const$5.get(seg); + public static MemorySegment GetDeviceAsyncEventSource(MemorySegment struct) { + return struct.get(GetDeviceAsyncEventSource$LAYOUT, GetDeviceAsyncEventSource$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceSubClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *) * } */ - public static void GetDeviceSubClass$set(MemorySegment seg, MemorySegment x) { - constants$9.const$5.set(seg, x); - } - public static MemorySegment GetDeviceSubClass$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$9.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceSubClass$set(MemorySegment seg, long index, MemorySegment x) { - constants$9.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceSubClass GetDeviceSubClass(MemorySegment segment, Arena scope) { - return GetDeviceSubClass.ofAddress(GetDeviceSubClass$get(segment), scope); + public static void GetDeviceAsyncEventSource(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceAsyncEventSource$LAYOUT, GetDeviceAsyncEventSource$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceProtocol)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *) * } */ - public interface GetDeviceProtocol { + public final static class CreateDeviceAsyncPort { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceProtocol fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$10.const$0, fi, constants$6.const$5, scope); + private CreateDeviceAsyncPort() { + // Should not be called directly } - static GetDeviceProtocol ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDeviceProtocol$VH() { - return constants$10.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceProtocol)(void*,UInt8*); - * } - */ - public static MemorySegment GetDeviceProtocol$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$10.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout CreateDeviceAsyncPort$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("CreateDeviceAsyncPort")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceProtocol)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *) * } */ - public static void GetDeviceProtocol$set(MemorySegment seg, MemorySegment x) { - constants$10.const$1.set(seg, x); - } - public static MemorySegment GetDeviceProtocol$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$10.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceProtocol$set(MemorySegment seg, long index, MemorySegment x) { - constants$10.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceProtocol GetDeviceProtocol(MemorySegment segment, Arena scope) { - return GetDeviceProtocol.ofAddress(GetDeviceProtocol$get(segment), scope); + public static final AddressLayout CreateDeviceAsyncPort$layout() { + return CreateDeviceAsyncPort$LAYOUT; } + + private static final long CreateDeviceAsyncPort$OFFSET = $LAYOUT.byteOffset(groupElement("CreateDeviceAsyncPort")); + /** - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *) * } */ - public interface GetDeviceVendor { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceVendor fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$10.const$2, fi, constants$6.const$5, scope); - } - static GetDeviceVendor ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long CreateDeviceAsyncPort$offset() { + return CreateDeviceAsyncPort$OFFSET; } - public static VarHandle GetDeviceVendor$VH() { - return constants$10.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *) * } */ - public static MemorySegment GetDeviceVendor$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$10.const$3.get(seg); + public static MemorySegment CreateDeviceAsyncPort(MemorySegment struct) { + return struct.get(CreateDeviceAsyncPort$LAYOUT, CreateDeviceAsyncPort$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * {@snippet lang=c : + * IOReturn (*CreateDeviceAsyncPort)(void *, mach_port_t *) * } */ - public static void GetDeviceVendor$set(MemorySegment seg, MemorySegment x) { - constants$10.const$3.set(seg, x); - } - public static MemorySegment GetDeviceVendor$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$10.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceVendor$set(MemorySegment seg, long index, MemorySegment x) { - constants$10.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceVendor GetDeviceVendor(MemorySegment segment, Arena scope) { - return GetDeviceVendor.ofAddress(GetDeviceVendor$get(segment), scope); + public static void CreateDeviceAsyncPort(MemorySegment struct, MemorySegment fieldValue) { + struct.set(CreateDeviceAsyncPort$LAYOUT, CreateDeviceAsyncPort$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetDeviceAsyncPort)(void *) * } */ - public interface GetDeviceProduct { + public final static class GetDeviceAsyncPort { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceProduct fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$10.const$4, fi, constants$6.const$5, scope); + private GetDeviceAsyncPort() { + // Should not be called directly } - static GetDeviceProduct ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDeviceProduct$VH() { - return constants$10.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); - * } - */ - public static MemorySegment GetDeviceProduct$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$10.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout GetDeviceAsyncPort$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceAsyncPort")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); + * Layout for field: + * {@snippet lang=c : + * mach_port_t (*GetDeviceAsyncPort)(void *) * } */ - public static void GetDeviceProduct$set(MemorySegment seg, MemorySegment x) { - constants$10.const$5.set(seg, x); - } - public static MemorySegment GetDeviceProduct$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$10.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceProduct$set(MemorySegment seg, long index, MemorySegment x) { - constants$10.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceProduct GetDeviceProduct(MemorySegment segment, Arena scope) { - return GetDeviceProduct.ofAddress(GetDeviceProduct$get(segment), scope); + public static final AddressLayout GetDeviceAsyncPort$layout() { + return GetDeviceAsyncPort$LAYOUT; } + + private static final long GetDeviceAsyncPort$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceAsyncPort")); + /** - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * Offset for field: + * {@snippet lang=c : + * mach_port_t (*GetDeviceAsyncPort)(void *) * } */ - public interface GetDeviceReleaseNumber { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceReleaseNumber fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$11.const$0, fi, constants$6.const$5, scope); - } - static GetDeviceReleaseNumber ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long GetDeviceAsyncPort$offset() { + return GetDeviceAsyncPort$OFFSET; } - public static VarHandle GetDeviceReleaseNumber$VH() { - return constants$11.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetDeviceAsyncPort)(void *) * } */ - public static MemorySegment GetDeviceReleaseNumber$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$11.const$1.get(seg); + public static MemorySegment GetDeviceAsyncPort(MemorySegment struct) { + return struct.get(GetDeviceAsyncPort$LAYOUT, GetDeviceAsyncPort$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetDeviceAsyncPort)(void *) * } */ - public static void GetDeviceReleaseNumber$set(MemorySegment seg, MemorySegment x) { - constants$11.const$1.set(seg, x); - } - public static MemorySegment GetDeviceReleaseNumber$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$11.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceReleaseNumber$set(MemorySegment seg, long index, MemorySegment x) { - constants$11.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceReleaseNumber GetDeviceReleaseNumber(MemorySegment segment, Arena scope) { - return GetDeviceReleaseNumber.ofAddress(GetDeviceReleaseNumber$get(segment), scope); + public static void GetDeviceAsyncPort(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceAsyncPort$LAYOUT, GetDeviceAsyncPort$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceAddress)(void*,USBDeviceAddress*); + * {@snippet lang=c : + * IOReturn (*USBDeviceOpen)(void *) * } */ - public interface GetDeviceAddress { + public final static class USBDeviceOpen { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceAddress fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$11.const$2, fi, constants$6.const$5, scope); + private USBDeviceOpen() { + // Should not be called directly } - static GetDeviceAddress ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDeviceAddress$VH() { - return constants$11.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceAddress)(void*,USBDeviceAddress*); - * } - */ - public static MemorySegment GetDeviceAddress$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$11.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBDeviceOpen$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceOpen")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceAddress)(void*,USBDeviceAddress*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceOpen)(void *) * } */ - public static void GetDeviceAddress$set(MemorySegment seg, MemorySegment x) { - constants$11.const$3.set(seg, x); - } - public static MemorySegment GetDeviceAddress$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$11.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceAddress$set(MemorySegment seg, long index, MemorySegment x) { - constants$11.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceAddress GetDeviceAddress(MemorySegment segment, Arena scope) { - return GetDeviceAddress.ofAddress(GetDeviceAddress$get(segment), scope); + public static final AddressLayout USBDeviceOpen$layout() { + return USBDeviceOpen$LAYOUT; } + + private static final long USBDeviceOpen$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceOpen")); + /** - * {@snippet : - * IOReturn (*GetDeviceBusPowerAvailable)(void*,UInt32*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceOpen)(void *) * } */ - public interface GetDeviceBusPowerAvailable { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceBusPowerAvailable fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$11.const$4, fi, constants$6.const$5, scope); - } - static GetDeviceBusPowerAvailable ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBDeviceOpen$offset() { + return USBDeviceOpen$OFFSET; } - public static VarHandle GetDeviceBusPowerAvailable$VH() { - return constants$11.const$5; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceBusPowerAvailable)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*USBDeviceOpen)(void *) * } */ - public static MemorySegment GetDeviceBusPowerAvailable$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$11.const$5.get(seg); + public static MemorySegment USBDeviceOpen(MemorySegment struct) { + return struct.get(USBDeviceOpen$LAYOUT, USBDeviceOpen$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceBusPowerAvailable)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*USBDeviceOpen)(void *) * } */ - public static void GetDeviceBusPowerAvailable$set(MemorySegment seg, MemorySegment x) { - constants$11.const$5.set(seg, x); - } - public static MemorySegment GetDeviceBusPowerAvailable$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$11.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceBusPowerAvailable$set(MemorySegment seg, long index, MemorySegment x) { - constants$11.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceBusPowerAvailable GetDeviceBusPowerAvailable(MemorySegment segment, Arena scope) { - return GetDeviceBusPowerAvailable.ofAddress(GetDeviceBusPowerAvailable$get(segment), scope); + public static void USBDeviceOpen(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceOpen$LAYOUT, USBDeviceOpen$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceSpeed)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBDeviceClose)(void *) * } */ - public interface GetDeviceSpeed { + public final static class USBDeviceClose { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceSpeed fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$12.const$0, fi, constants$6.const$5, scope); + private USBDeviceClose() { + // Should not be called directly } - static GetDeviceSpeed ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout USBDeviceClose$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceClose")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceClose)(void *) + * } + */ + public static final AddressLayout USBDeviceClose$layout() { + return USBDeviceClose$LAYOUT; + } + + private static final long USBDeviceClose$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceClose")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceClose)(void *) + * } + */ + public static final long USBDeviceClose$offset() { + return USBDeviceClose$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceClose)(void *) + * } + */ + public static MemorySegment USBDeviceClose(MemorySegment struct) { + return struct.get(USBDeviceClose$LAYOUT, USBDeviceClose$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceClose)(void *) + * } + */ + public static void USBDeviceClose(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceClose$LAYOUT, USBDeviceClose$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceClass)(void *, UInt8 *) + * } + */ + public final static class GetDeviceClass { + + private GetDeviceClass() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceClass$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceClass)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetDeviceClass$layout() { + return GetDeviceClass$LAYOUT; + } + + private static final long GetDeviceClass$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceClass)(void *, UInt8 *) + * } + */ + public static final long GetDeviceClass$offset() { + return GetDeviceClass$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceClass)(void *, UInt8 *) + * } + */ + public static MemorySegment GetDeviceClass(MemorySegment struct) { + return struct.get(GetDeviceClass$LAYOUT, GetDeviceClass$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceClass)(void *, UInt8 *) + * } + */ + public static void GetDeviceClass(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceClass$LAYOUT, GetDeviceClass$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *) + * } + */ + public final static class GetDeviceSubClass { + + private GetDeviceSubClass() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceSubClass$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceSubClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetDeviceSubClass$layout() { + return GetDeviceSubClass$LAYOUT; + } + + private static final long GetDeviceSubClass$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceSubClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *) + * } + */ + public static final long GetDeviceSubClass$offset() { + return GetDeviceSubClass$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *) + * } + */ + public static MemorySegment GetDeviceSubClass(MemorySegment struct) { + return struct.get(GetDeviceSubClass$LAYOUT, GetDeviceSubClass$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSubClass)(void *, UInt8 *) + * } + */ + public static void GetDeviceSubClass(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceSubClass$LAYOUT, GetDeviceSubClass$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *) + * } + */ + public final static class GetDeviceProtocol { + + private GetDeviceProtocol() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceProtocol$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceProtocol")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetDeviceProtocol$layout() { + return GetDeviceProtocol$LAYOUT; + } + + private static final long GetDeviceProtocol$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceProtocol")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *) + * } + */ + public static final long GetDeviceProtocol$offset() { + return GetDeviceProtocol$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *) + * } + */ + public static MemorySegment GetDeviceProtocol(MemorySegment struct) { + return struct.get(GetDeviceProtocol$LAYOUT, GetDeviceProtocol$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProtocol)(void *, UInt8 *) + * } + */ + public static void GetDeviceProtocol(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceProtocol$LAYOUT, GetDeviceProtocol$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public final static class GetDeviceVendor { + + private GetDeviceVendor() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceVendor$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceVendor")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceVendor$layout() { + return GetDeviceVendor$LAYOUT; + } + + private static final long GetDeviceVendor$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceVendor")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static final long GetDeviceVendor$offset() { + return GetDeviceVendor$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceVendor(MemorySegment struct) { + return struct.get(GetDeviceVendor$LAYOUT, GetDeviceVendor$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static void GetDeviceVendor(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceVendor$LAYOUT, GetDeviceVendor$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public final static class GetDeviceProduct { + + private GetDeviceProduct() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceProduct$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceProduct")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceProduct$layout() { + return GetDeviceProduct$LAYOUT; + } + + private static final long GetDeviceProduct$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceProduct")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static final long GetDeviceProduct$offset() { + return GetDeviceProduct$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceProduct(MemorySegment struct) { + return struct.get(GetDeviceProduct$LAYOUT, GetDeviceProduct$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static void GetDeviceProduct(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceProduct$LAYOUT, GetDeviceProduct$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public final static class GetDeviceReleaseNumber { + + private GetDeviceReleaseNumber() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceReleaseNumber$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceReleaseNumber")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceReleaseNumber$layout() { + return GetDeviceReleaseNumber$LAYOUT; + } + + private static final long GetDeviceReleaseNumber$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceReleaseNumber")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static final long GetDeviceReleaseNumber$offset() { + return GetDeviceReleaseNumber$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceReleaseNumber(MemorySegment struct) { + return struct.get(GetDeviceReleaseNumber$LAYOUT, GetDeviceReleaseNumber$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static void GetDeviceReleaseNumber(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceReleaseNumber$LAYOUT, GetDeviceReleaseNumber$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *) + * } + */ + public final static class GetDeviceAddress { + + private GetDeviceAddress() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceAddress$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceAddress")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *) + * } + */ + public static final AddressLayout GetDeviceAddress$layout() { + return GetDeviceAddress$LAYOUT; + } + + private static final long GetDeviceAddress$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceAddress")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *) + * } + */ + public static final long GetDeviceAddress$offset() { + return GetDeviceAddress$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *) + * } + */ + public static MemorySegment GetDeviceAddress(MemorySegment struct) { + return struct.get(GetDeviceAddress$LAYOUT, GetDeviceAddress$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceAddress)(void *, USBDeviceAddress *) + * } + */ + public static void GetDeviceAddress(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceAddress$LAYOUT, GetDeviceAddress$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *) + * } + */ + public final static class GetDeviceBusPowerAvailable { + + private GetDeviceBusPowerAvailable() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceBusPowerAvailable$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceBusPowerAvailable")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *) + * } + */ + public static final AddressLayout GetDeviceBusPowerAvailable$layout() { + return GetDeviceBusPowerAvailable$LAYOUT; + } + + private static final long GetDeviceBusPowerAvailable$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceBusPowerAvailable")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *) + * } + */ + public static final long GetDeviceBusPowerAvailable$offset() { + return GetDeviceBusPowerAvailable$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *) + * } + */ + public static MemorySegment GetDeviceBusPowerAvailable(MemorySegment struct) { + return struct.get(GetDeviceBusPowerAvailable$LAYOUT, GetDeviceBusPowerAvailable$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceBusPowerAvailable)(void *, UInt32 *) + * } + */ + public static void GetDeviceBusPowerAvailable(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceBusPowerAvailable$LAYOUT, GetDeviceBusPowerAvailable$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *) + * } + */ + public final static class GetDeviceSpeed { + + private GetDeviceSpeed() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceSpeed$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceSpeed")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetDeviceSpeed$layout() { + return GetDeviceSpeed$LAYOUT; + } + + private static final long GetDeviceSpeed$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceSpeed")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *) + * } + */ + public static final long GetDeviceSpeed$offset() { + return GetDeviceSpeed$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *) + * } + */ + public static MemorySegment GetDeviceSpeed(MemorySegment struct) { + return struct.get(GetDeviceSpeed$LAYOUT, GetDeviceSpeed$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceSpeed)(void *, UInt8 *) + * } + */ + public static void GetDeviceSpeed(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceSpeed$LAYOUT, GetDeviceSpeed$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *) + * } + */ + public final static class GetNumberOfConfigurations { + + private GetNumberOfConfigurations() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetNumberOfConfigurations$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetNumberOfConfigurations")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetNumberOfConfigurations$layout() { + return GetNumberOfConfigurations$LAYOUT; + } + + private static final long GetNumberOfConfigurations$OFFSET = $LAYOUT.byteOffset(groupElement("GetNumberOfConfigurations")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *) + * } + */ + public static final long GetNumberOfConfigurations$offset() { + return GetNumberOfConfigurations$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *) + * } + */ + public static MemorySegment GetNumberOfConfigurations(MemorySegment struct) { + return struct.get(GetNumberOfConfigurations$LAYOUT, GetNumberOfConfigurations$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetNumberOfConfigurations)(void *, UInt8 *) + * } + */ + public static void GetNumberOfConfigurations(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetNumberOfConfigurations$LAYOUT, GetNumberOfConfigurations$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public final static class GetLocationID { + + private GetLocationID() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetLocationID$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetLocationID")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static final AddressLayout GetLocationID$layout() { + return GetLocationID$LAYOUT; + } + + private static final long GetLocationID$OFFSET = $LAYOUT.byteOffset(groupElement("GetLocationID")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static final long GetLocationID$offset() { + return GetLocationID$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static MemorySegment GetLocationID(MemorySegment struct) { + return struct.get(GetLocationID$LAYOUT, GetLocationID$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static void GetLocationID(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetLocationID$LAYOUT, GetLocationID$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *) + * } + */ + public final static class GetConfigurationDescriptorPtr { + + private GetConfigurationDescriptorPtr() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetConfigurationDescriptorPtr$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetConfigurationDescriptorPtr")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *) + * } + */ + public static final AddressLayout GetConfigurationDescriptorPtr$layout() { + return GetConfigurationDescriptorPtr$LAYOUT; + } + + private static final long GetConfigurationDescriptorPtr$OFFSET = $LAYOUT.byteOffset(groupElement("GetConfigurationDescriptorPtr")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *) + * } + */ + public static final long GetConfigurationDescriptorPtr$offset() { + return GetConfigurationDescriptorPtr$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *) + * } + */ + public static MemorySegment GetConfigurationDescriptorPtr(MemorySegment struct) { + return struct.get(GetConfigurationDescriptorPtr$LAYOUT, GetConfigurationDescriptorPtr$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationDescriptorPtr)(void *, UInt8, IOUSBConfigurationDescriptorPtr *) + * } + */ + public static void GetConfigurationDescriptorPtr(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetConfigurationDescriptorPtr$LAYOUT, GetConfigurationDescriptorPtr$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetConfiguration)(void *, UInt8 *) + * } + */ + public final static class GetConfiguration { + + private GetConfiguration() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetConfiguration$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetConfiguration")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetConfiguration)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetConfiguration$layout() { + return GetConfiguration$LAYOUT; + } + + private static final long GetConfiguration$OFFSET = $LAYOUT.byteOffset(groupElement("GetConfiguration")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetConfiguration)(void *, UInt8 *) + * } + */ + public static final long GetConfiguration$offset() { + return GetConfiguration$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetConfiguration)(void *, UInt8 *) + * } + */ + public static MemorySegment GetConfiguration(MemorySegment struct) { + return struct.get(GetConfiguration$LAYOUT, GetConfiguration$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetConfiguration)(void *, UInt8 *) + * } + */ + public static void GetConfiguration(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetConfiguration$LAYOUT, GetConfiguration$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*SetConfiguration)(void *, UInt8) + * } + */ + public final static class SetConfiguration { + + private SetConfiguration() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetDeviceSpeed$VH() { - return constants$12.const$1; + private static final AddressLayout SetConfiguration$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("SetConfiguration")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*SetConfiguration)(void *, UInt8) + * } + */ + public static final AddressLayout SetConfiguration$layout() { + return SetConfiguration$LAYOUT; + } + + private static final long SetConfiguration$OFFSET = $LAYOUT.byteOffset(groupElement("SetConfiguration")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*SetConfiguration)(void *, UInt8) + * } + */ + public static final long SetConfiguration$offset() { + return SetConfiguration$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceSpeed)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*SetConfiguration)(void *, UInt8) * } */ - public static MemorySegment GetDeviceSpeed$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$12.const$1.get(seg); + public static MemorySegment SetConfiguration(MemorySegment struct) { + return struct.get(SetConfiguration$LAYOUT, SetConfiguration$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceSpeed)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*SetConfiguration)(void *, UInt8) + * } + */ + public static void SetConfiguration(MemorySegment struct, MemorySegment fieldValue) { + struct.set(SetConfiguration$LAYOUT, SetConfiguration$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public final static class GetBusFrameNumber { + + private GetBusFrameNumber() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetBusFrameNumber$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetBusFrameNumber")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) * } */ - public static void GetDeviceSpeed$set(MemorySegment seg, MemorySegment x) { - constants$12.const$1.set(seg, x); + public static final AddressLayout GetBusFrameNumber$layout() { + return GetBusFrameNumber$LAYOUT; } - public static MemorySegment GetDeviceSpeed$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$12.const$1.get(seg.asSlice(index*sizeof())); + + private static final long GetBusFrameNumber$OFFSET = $LAYOUT.byteOffset(groupElement("GetBusFrameNumber")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static final long GetBusFrameNumber$offset() { + return GetBusFrameNumber$OFFSET; } - public static void GetDeviceSpeed$set(MemorySegment seg, long index, MemorySegment x) { - constants$12.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static MemorySegment GetBusFrameNumber(MemorySegment struct) { + return struct.get(GetBusFrameNumber$LAYOUT, GetBusFrameNumber$OFFSET); } - public static GetDeviceSpeed GetDeviceSpeed(MemorySegment segment, Arena scope) { - return GetDeviceSpeed.ofAddress(GetDeviceSpeed$get(segment), scope); + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static void GetBusFrameNumber(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetBusFrameNumber$LAYOUT, GetBusFrameNumber$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetNumberOfConfigurations)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ResetDevice)(void *) * } */ - public interface GetNumberOfConfigurations { + public final static class ResetDevice { + + private ResetDevice() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetNumberOfConfigurations fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$12.const$2, fi, constants$6.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static GetNumberOfConfigurations ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetNumberOfConfigurations$VH() { - return constants$12.const$3; + private static final AddressLayout ResetDevice$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ResetDevice")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ResetDevice)(void *) + * } + */ + public static final AddressLayout ResetDevice$layout() { + return ResetDevice$LAYOUT; + } + + private static final long ResetDevice$OFFSET = $LAYOUT.byteOffset(groupElement("ResetDevice")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ResetDevice)(void *) + * } + */ + public static final long ResetDevice$offset() { + return ResetDevice$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetNumberOfConfigurations)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ResetDevice)(void *) * } */ - public static MemorySegment GetNumberOfConfigurations$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$12.const$3.get(seg); + public static MemorySegment ResetDevice(MemorySegment struct) { + return struct.get(ResetDevice$LAYOUT, ResetDevice$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetNumberOfConfigurations)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ResetDevice)(void *) + * } + */ + public static void ResetDevice(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ResetDevice$LAYOUT, ResetDevice$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *) + * } + */ + public final static class DeviceRequest { + + private DeviceRequest() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout DeviceRequest$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("DeviceRequest")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *) * } */ - public static void GetNumberOfConfigurations$set(MemorySegment seg, MemorySegment x) { - constants$12.const$3.set(seg, x); + public static final AddressLayout DeviceRequest$layout() { + return DeviceRequest$LAYOUT; } - public static MemorySegment GetNumberOfConfigurations$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$12.const$3.get(seg.asSlice(index*sizeof())); + + private static final long DeviceRequest$OFFSET = $LAYOUT.byteOffset(groupElement("DeviceRequest")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *) + * } + */ + public static final long DeviceRequest$offset() { + return DeviceRequest$OFFSET; } - public static void GetNumberOfConfigurations$set(MemorySegment seg, long index, MemorySegment x) { - constants$12.const$3.set(seg.asSlice(index*sizeof()), x); + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *) + * } + */ + public static MemorySegment DeviceRequest(MemorySegment struct) { + return struct.get(DeviceRequest$LAYOUT, DeviceRequest$OFFSET); } - public static GetNumberOfConfigurations GetNumberOfConfigurations(MemorySegment segment, Arena scope) { - return GetNumberOfConfigurations.ofAddress(GetNumberOfConfigurations$get(segment), scope); + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequest)(void *, IOUSBDevRequest *) + * } + */ + public static void DeviceRequest(MemorySegment struct, MemorySegment fieldValue) { + struct.set(DeviceRequest$LAYOUT, DeviceRequest$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *) * } */ - public interface GetLocationID { + public final static class DeviceRequestAsync { + + private DeviceRequestAsync() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetLocationID fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$12.const$4, fi, constants$6.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static GetLocationID ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetLocationID$VH() { - return constants$12.const$5; + private static final AddressLayout DeviceRequestAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("DeviceRequestAsync")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout DeviceRequestAsync$layout() { + return DeviceRequestAsync$LAYOUT; + } + + private static final long DeviceRequestAsync$OFFSET = $LAYOUT.byteOffset(groupElement("DeviceRequestAsync")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static final long DeviceRequestAsync$offset() { + return DeviceRequestAsync$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *) * } */ - public static MemorySegment GetLocationID$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$12.const$5.get(seg); + public static MemorySegment DeviceRequestAsync(MemorySegment struct) { + return struct.get(DeviceRequestAsync$LAYOUT, DeviceRequestAsync$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsync)(void *, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static void DeviceRequestAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(DeviceRequestAsync$LAYOUT, DeviceRequestAsync$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *) + * } + */ + public final static class CreateInterfaceIterator { + + private CreateInterfaceIterator() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout CreateInterfaceIterator$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("CreateInterfaceIterator")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *) + * } + */ + public static final AddressLayout CreateInterfaceIterator$layout() { + return CreateInterfaceIterator$LAYOUT; + } + + private static final long CreateInterfaceIterator$OFFSET = $LAYOUT.byteOffset(groupElement("CreateInterfaceIterator")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *) + * } + */ + public static final long CreateInterfaceIterator$offset() { + return CreateInterfaceIterator$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *) * } */ - public static void GetLocationID$set(MemorySegment seg, MemorySegment x) { - constants$12.const$5.set(seg, x); + public static MemorySegment CreateInterfaceIterator(MemorySegment struct) { + return struct.get(CreateInterfaceIterator$LAYOUT, CreateInterfaceIterator$OFFSET); } - public static MemorySegment GetLocationID$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$12.const$5.get(seg.asSlice(index*sizeof())); + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceIterator)(void *, IOUSBFindInterfaceRequest *, io_iterator_t *) + * } + */ + public static void CreateInterfaceIterator(MemorySegment struct, MemorySegment fieldValue) { + struct.set(CreateInterfaceIterator$LAYOUT, CreateInterfaceIterator$OFFSET, fieldValue); } - public static void GetLocationID$set(MemorySegment seg, long index, MemorySegment x) { - constants$12.const$5.set(seg.asSlice(index*sizeof()), x); + + /** + * {@snippet lang=c : + * IOReturn (*USBDeviceOpenSeize)(void *) + * } + */ + public final static class USBDeviceOpenSeize { + + private USBDeviceOpenSeize() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } - public static GetLocationID GetLocationID(MemorySegment segment, Arena scope) { - return GetLocationID.ofAddress(GetLocationID$get(segment), scope); + + private static final AddressLayout USBDeviceOpenSeize$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceOpenSeize")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceOpenSeize)(void *) + * } + */ + public static final AddressLayout USBDeviceOpenSeize$layout() { + return USBDeviceOpenSeize$LAYOUT; } + + private static final long USBDeviceOpenSeize$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceOpenSeize")); + /** - * {@snippet : - * IOReturn (*GetConfigurationDescriptorPtr)(void*,UInt8,IOUSBConfigurationDescriptorPtr*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceOpenSeize)(void *) * } */ - public interface GetConfigurationDescriptorPtr { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(GetConfigurationDescriptorPtr fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$13.const$1, fi, constants$13.const$0, scope); - } - static GetConfigurationDescriptorPtr ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$13.const$2.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBDeviceOpenSeize$offset() { + return USBDeviceOpenSeize$OFFSET; } - public static VarHandle GetConfigurationDescriptorPtr$VH() { - return constants$13.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetConfigurationDescriptorPtr)(void*,UInt8,IOUSBConfigurationDescriptorPtr*); + * {@snippet lang=c : + * IOReturn (*USBDeviceOpenSeize)(void *) * } */ - public static MemorySegment GetConfigurationDescriptorPtr$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$13.const$3.get(seg); + public static MemorySegment USBDeviceOpenSeize(MemorySegment struct) { + return struct.get(USBDeviceOpenSeize$LAYOUT, USBDeviceOpenSeize$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetConfigurationDescriptorPtr)(void*,UInt8,IOUSBConfigurationDescriptorPtr*); + * {@snippet lang=c : + * IOReturn (*USBDeviceOpenSeize)(void *) * } */ - public static void GetConfigurationDescriptorPtr$set(MemorySegment seg, MemorySegment x) { - constants$13.const$3.set(seg, x); - } - public static MemorySegment GetConfigurationDescriptorPtr$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$13.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetConfigurationDescriptorPtr$set(MemorySegment seg, long index, MemorySegment x) { - constants$13.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetConfigurationDescriptorPtr GetConfigurationDescriptorPtr(MemorySegment segment, Arena scope) { - return GetConfigurationDescriptorPtr.ofAddress(GetConfigurationDescriptorPtr$get(segment), scope); + public static void USBDeviceOpenSeize(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceOpenSeize$LAYOUT, USBDeviceOpenSeize$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetConfiguration)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *) * } */ - public interface GetConfiguration { + public final static class DeviceRequestTO { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetConfiguration fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$13.const$4, fi, constants$6.const$5, scope); + private DeviceRequestTO() { + // Should not be called directly } - static GetConfiguration ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetConfiguration$VH() { - return constants$13.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetConfiguration)(void*,UInt8*); - * } - */ - public static MemorySegment GetConfiguration$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$13.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout DeviceRequestTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("DeviceRequestTO")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetConfiguration)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *) * } */ - public static void GetConfiguration$set(MemorySegment seg, MemorySegment x) { - constants$13.const$5.set(seg, x); - } - public static MemorySegment GetConfiguration$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$13.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetConfiguration$set(MemorySegment seg, long index, MemorySegment x) { - constants$13.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetConfiguration GetConfiguration(MemorySegment segment, Arena scope) { - return GetConfiguration.ofAddress(GetConfiguration$get(segment), scope); + public static final AddressLayout DeviceRequestTO$layout() { + return DeviceRequestTO$LAYOUT; } + + private static final long DeviceRequestTO$OFFSET = $LAYOUT.byteOffset(groupElement("DeviceRequestTO")); + /** - * {@snippet : - * IOReturn (*SetConfiguration)(void*,UInt8); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *) * } */ - public interface SetConfiguration { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(SetConfiguration fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$14.const$1, fi, constants$14.const$0, scope); - } - static SetConfiguration ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long DeviceRequestTO$offset() { + return DeviceRequestTO$OFFSET; } - public static VarHandle SetConfiguration$VH() { - return constants$14.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*SetConfiguration)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *) * } */ - public static MemorySegment SetConfiguration$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$14.const$3.get(seg); + public static MemorySegment DeviceRequestTO(MemorySegment struct) { + return struct.get(DeviceRequestTO$LAYOUT, DeviceRequestTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*SetConfiguration)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*DeviceRequestTO)(void *, IOUSBDevRequestTO *) * } */ - public static void SetConfiguration$set(MemorySegment seg, MemorySegment x) { - constants$14.const$3.set(seg, x); - } - public static MemorySegment SetConfiguration$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$14.const$3.get(seg.asSlice(index*sizeof())); - } - public static void SetConfiguration$set(MemorySegment seg, long index, MemorySegment x) { - constants$14.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static SetConfiguration SetConfiguration(MemorySegment segment, Arena scope) { - return SetConfiguration.ofAddress(SetConfiguration$get(segment), scope); + public static void DeviceRequestTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(DeviceRequestTO$LAYOUT, DeviceRequestTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public interface GetBusFrameNumber { + public final static class DeviceRequestAsyncTO { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(GetBusFrameNumber fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$14.const$5, fi, constants$14.const$4, scope); + private DeviceRequestAsyncTO() { + // Should not be called directly } - static GetBusFrameNumber ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$15.const$0.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetBusFrameNumber$VH() { - return constants$15.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); - * } - */ - public static MemorySegment GetBusFrameNumber$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$15.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout DeviceRequestAsyncTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("DeviceRequestAsyncTO")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public static void GetBusFrameNumber$set(MemorySegment seg, MemorySegment x) { - constants$15.const$1.set(seg, x); - } - public static MemorySegment GetBusFrameNumber$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$15.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetBusFrameNumber$set(MemorySegment seg, long index, MemorySegment x) { - constants$15.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetBusFrameNumber GetBusFrameNumber(MemorySegment segment, Arena scope) { - return GetBusFrameNumber.ofAddress(GetBusFrameNumber$get(segment), scope); + public static final AddressLayout DeviceRequestAsyncTO$layout() { + return DeviceRequestAsyncTO$LAYOUT; } + + private static final long DeviceRequestAsyncTO$OFFSET = $LAYOUT.byteOffset(groupElement("DeviceRequestAsyncTO")); + /** - * {@snippet : - * IOReturn (*ResetDevice)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public interface ResetDevice { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(ResetDevice fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$15.const$2, fi, constants$5.const$5, scope); - } - static ResetDevice ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long DeviceRequestAsyncTO$offset() { + return DeviceRequestAsyncTO$OFFSET; } - public static VarHandle ResetDevice$VH() { - return constants$15.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*ResetDevice)(void*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public static MemorySegment ResetDevice$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$15.const$3.get(seg); + public static MemorySegment DeviceRequestAsyncTO(MemorySegment struct) { + return struct.get(DeviceRequestAsyncTO$LAYOUT, DeviceRequestAsyncTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ResetDevice)(void*); + * {@snippet lang=c : + * IOReturn (*DeviceRequestAsyncTO)(void *, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public static void ResetDevice$set(MemorySegment seg, MemorySegment x) { - constants$15.const$3.set(seg, x); - } - public static MemorySegment ResetDevice$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$15.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ResetDevice$set(MemorySegment seg, long index, MemorySegment x) { - constants$15.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static ResetDevice ResetDevice(MemorySegment segment, Arena scope) { - return ResetDevice.ofAddress(ResetDevice$get(segment), scope); + public static void DeviceRequestAsyncTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(DeviceRequestAsyncTO$LAYOUT, DeviceRequestAsyncTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*DeviceRequest)(void*,IOUSBDevRequest*); + * {@snippet lang=c : + * IOReturn (*USBDeviceSuspend)(void *, Boolean) * } */ - public interface DeviceRequest { + public final static class USBDeviceSuspend { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(DeviceRequest fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$15.const$4, fi, constants$6.const$5, scope); + private USBDeviceSuspend() { + // Should not be called directly } - static DeviceRequest ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle DeviceRequest$VH() { - return constants$15.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*DeviceRequest)(void*,IOUSBDevRequest*); - * } - */ - public static MemorySegment DeviceRequest$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$15.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBDeviceSuspend$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceSuspend")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*DeviceRequest)(void*,IOUSBDevRequest*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceSuspend)(void *, Boolean) * } */ - public static void DeviceRequest$set(MemorySegment seg, MemorySegment x) { - constants$15.const$5.set(seg, x); - } - public static MemorySegment DeviceRequest$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$15.const$5.get(seg.asSlice(index*sizeof())); - } - public static void DeviceRequest$set(MemorySegment seg, long index, MemorySegment x) { - constants$15.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static DeviceRequest DeviceRequest(MemorySegment segment, Arena scope) { - return DeviceRequest.ofAddress(DeviceRequest$get(segment), scope); + public static final AddressLayout USBDeviceSuspend$layout() { + return USBDeviceSuspend$LAYOUT; } + + private static final long USBDeviceSuspend$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceSuspend")); + /** - * {@snippet : - * IOReturn (*DeviceRequestAsync)(void*,IOUSBDevRequest*,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceSuspend)(void *, Boolean) * } */ - public interface DeviceRequestAsync { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3); - static MemorySegment allocate(DeviceRequestAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$16.const$1, fi, constants$16.const$0, scope); - } - static DeviceRequestAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3) -> { - try { - return (int)constants$16.const$2.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBDeviceSuspend$offset() { + return USBDeviceSuspend$OFFSET; } - public static VarHandle DeviceRequestAsync$VH() { - return constants$16.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*DeviceRequestAsync)(void*,IOUSBDevRequest*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBDeviceSuspend)(void *, Boolean) * } */ - public static MemorySegment DeviceRequestAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$16.const$3.get(seg); + public static MemorySegment USBDeviceSuspend(MemorySegment struct) { + return struct.get(USBDeviceSuspend$LAYOUT, USBDeviceSuspend$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*DeviceRequestAsync)(void*,IOUSBDevRequest*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBDeviceSuspend)(void *, Boolean) * } */ - public static void DeviceRequestAsync$set(MemorySegment seg, MemorySegment x) { - constants$16.const$3.set(seg, x); - } - public static MemorySegment DeviceRequestAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$16.const$3.get(seg.asSlice(index*sizeof())); - } - public static void DeviceRequestAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$16.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static DeviceRequestAsync DeviceRequestAsync(MemorySegment segment, Arena scope) { - return DeviceRequestAsync.ofAddress(DeviceRequestAsync$get(segment), scope); + public static void USBDeviceSuspend(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceSuspend$LAYOUT, USBDeviceSuspend$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*CreateInterfaceIterator)(void*,IOUSBFindInterfaceRequest*,io_iterator_t*); + * {@snippet lang=c : + * IOReturn (*USBDeviceAbortPipeZero)(void *) * } */ - public interface CreateInterfaceIterator { + public final static class USBDeviceAbortPipeZero { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(CreateInterfaceIterator fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$16.const$4, fi, constants$14.const$4, scope); + private USBDeviceAbortPipeZero() { + // Should not be called directly } - static CreateInterfaceIterator ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$15.const$0.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle CreateInterfaceIterator$VH() { - return constants$16.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*CreateInterfaceIterator)(void*,IOUSBFindInterfaceRequest*,io_iterator_t*); - * } - */ - public static MemorySegment CreateInterfaceIterator$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$16.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBDeviceAbortPipeZero$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceAbortPipeZero")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*CreateInterfaceIterator)(void*,IOUSBFindInterfaceRequest*,io_iterator_t*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceAbortPipeZero)(void *) * } */ - public static void CreateInterfaceIterator$set(MemorySegment seg, MemorySegment x) { - constants$16.const$5.set(seg, x); - } - public static MemorySegment CreateInterfaceIterator$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$16.const$5.get(seg.asSlice(index*sizeof())); - } - public static void CreateInterfaceIterator$set(MemorySegment seg, long index, MemorySegment x) { - constants$16.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static CreateInterfaceIterator CreateInterfaceIterator(MemorySegment segment, Arena scope) { - return CreateInterfaceIterator.ofAddress(CreateInterfaceIterator$get(segment), scope); + public static final AddressLayout USBDeviceAbortPipeZero$layout() { + return USBDeviceAbortPipeZero$LAYOUT; } + + private static final long USBDeviceAbortPipeZero$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceAbortPipeZero")); + /** - * {@snippet : - * IOReturn (*USBDeviceOpenSeize)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceAbortPipeZero)(void *) * } */ - public interface USBDeviceOpenSeize { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBDeviceOpenSeize fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$17.const$0, fi, constants$5.const$5, scope); - } - static USBDeviceOpenSeize ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBDeviceAbortPipeZero$offset() { + return USBDeviceAbortPipeZero$OFFSET; } - public static VarHandle USBDeviceOpenSeize$VH() { - return constants$17.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceOpenSeize)(void*); + * {@snippet lang=c : + * IOReturn (*USBDeviceAbortPipeZero)(void *) * } */ - public static MemorySegment USBDeviceOpenSeize$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$17.const$1.get(seg); + public static MemorySegment USBDeviceAbortPipeZero(MemorySegment struct) { + return struct.get(USBDeviceAbortPipeZero$LAYOUT, USBDeviceAbortPipeZero$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceOpenSeize)(void*); + * {@snippet lang=c : + * IOReturn (*USBDeviceAbortPipeZero)(void *) * } */ - public static void USBDeviceOpenSeize$set(MemorySegment seg, MemorySegment x) { - constants$17.const$1.set(seg, x); - } - public static MemorySegment USBDeviceOpenSeize$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$17.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBDeviceOpenSeize$set(MemorySegment seg, long index, MemorySegment x) { - constants$17.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBDeviceOpenSeize USBDeviceOpenSeize(MemorySegment segment, Arena scope) { - return USBDeviceOpenSeize.ofAddress(USBDeviceOpenSeize$get(segment), scope); + public static void USBDeviceAbortPipeZero(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceAbortPipeZero$LAYOUT, USBDeviceAbortPipeZero$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*DeviceRequestTO)(void*,IOUSBDevRequestTO*); + * {@snippet lang=c : + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *) * } */ - public interface DeviceRequestTO { + public final static class USBGetManufacturerStringIndex { + + private USBGetManufacturerStringIndex() { + // Should not be called directly + } - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(DeviceRequestTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$17.const$2, fi, constants$6.const$5, scope); + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static DeviceRequestTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle DeviceRequestTO$VH() { - return constants$17.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*DeviceRequestTO)(void*,IOUSBDevRequestTO*); - * } - */ - public static MemorySegment DeviceRequestTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$17.const$3.get(seg); - } + private static final AddressLayout USBGetManufacturerStringIndex$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBGetManufacturerStringIndex")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*DeviceRequestTO)(void*,IOUSBDevRequestTO*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *) * } */ - public static void DeviceRequestTO$set(MemorySegment seg, MemorySegment x) { - constants$17.const$3.set(seg, x); - } - public static MemorySegment DeviceRequestTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$17.const$3.get(seg.asSlice(index*sizeof())); - } - public static void DeviceRequestTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$17.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static DeviceRequestTO DeviceRequestTO(MemorySegment segment, Arena scope) { - return DeviceRequestTO.ofAddress(DeviceRequestTO$get(segment), scope); + public static final AddressLayout USBGetManufacturerStringIndex$layout() { + return USBGetManufacturerStringIndex$LAYOUT; } + + private static final long USBGetManufacturerStringIndex$OFFSET = $LAYOUT.byteOffset(groupElement("USBGetManufacturerStringIndex")); + /** - * {@snippet : - * IOReturn (*DeviceRequestAsyncTO)(void*,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *) * } */ - public interface DeviceRequestAsyncTO { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3); - static MemorySegment allocate(DeviceRequestAsyncTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$17.const$4, fi, constants$16.const$0, scope); - } - static DeviceRequestAsyncTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3) -> { - try { - return (int)constants$16.const$2.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBGetManufacturerStringIndex$offset() { + return USBGetManufacturerStringIndex$OFFSET; } - public static VarHandle DeviceRequestAsyncTO$VH() { - return constants$17.const$5; - } /** * Getter for field: - * {@snippet : - * IOReturn (*DeviceRequestAsyncTO)(void*,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *) * } */ - public static MemorySegment DeviceRequestAsyncTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$17.const$5.get(seg); + public static MemorySegment USBGetManufacturerStringIndex(MemorySegment struct) { + return struct.get(USBGetManufacturerStringIndex$LAYOUT, USBGetManufacturerStringIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*DeviceRequestAsyncTO)(void*,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBGetManufacturerStringIndex)(void *, UInt8 *) * } */ - public static void DeviceRequestAsyncTO$set(MemorySegment seg, MemorySegment x) { - constants$17.const$5.set(seg, x); - } - public static MemorySegment DeviceRequestAsyncTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$17.const$5.get(seg.asSlice(index*sizeof())); - } - public static void DeviceRequestAsyncTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$17.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static DeviceRequestAsyncTO DeviceRequestAsyncTO(MemorySegment segment, Arena scope) { - return DeviceRequestAsyncTO.ofAddress(DeviceRequestAsyncTO$get(segment), scope); + public static void USBGetManufacturerStringIndex(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBGetManufacturerStringIndex$LAYOUT, USBGetManufacturerStringIndex$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBDeviceSuspend)(void*,Boolean); + * {@snippet lang=c : + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *) * } */ - public interface USBDeviceSuspend { + public final static class USBGetProductStringIndex { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(USBDeviceSuspend fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$18.const$0, fi, constants$14.const$0, scope); + private USBGetProductStringIndex() { + // Should not be called directly } - static USBDeviceSuspend ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle USBDeviceSuspend$VH() { - return constants$18.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceSuspend)(void*,Boolean); - * } - */ - public static MemorySegment USBDeviceSuspend$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$18.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBGetProductStringIndex$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBGetProductStringIndex")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceSuspend)(void*,Boolean); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *) * } */ - public static void USBDeviceSuspend$set(MemorySegment seg, MemorySegment x) { - constants$18.const$1.set(seg, x); - } - public static MemorySegment USBDeviceSuspend$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$18.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBDeviceSuspend$set(MemorySegment seg, long index, MemorySegment x) { - constants$18.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBDeviceSuspend USBDeviceSuspend(MemorySegment segment, Arena scope) { - return USBDeviceSuspend.ofAddress(USBDeviceSuspend$get(segment), scope); + public static final AddressLayout USBGetProductStringIndex$layout() { + return USBGetProductStringIndex$LAYOUT; } + + private static final long USBGetProductStringIndex$OFFSET = $LAYOUT.byteOffset(groupElement("USBGetProductStringIndex")); + /** - * {@snippet : - * IOReturn (*USBDeviceAbortPipeZero)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *) * } */ - public interface USBDeviceAbortPipeZero { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBDeviceAbortPipeZero fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$18.const$2, fi, constants$5.const$5, scope); - } - static USBDeviceAbortPipeZero ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBGetProductStringIndex$offset() { + return USBGetProductStringIndex$OFFSET; } - public static VarHandle USBDeviceAbortPipeZero$VH() { - return constants$18.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceAbortPipeZero)(void*); + * {@snippet lang=c : + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *) * } */ - public static MemorySegment USBDeviceAbortPipeZero$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$18.const$3.get(seg); + public static MemorySegment USBGetProductStringIndex(MemorySegment struct) { + return struct.get(USBGetProductStringIndex$LAYOUT, USBGetProductStringIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceAbortPipeZero)(void*); + * {@snippet lang=c : + * IOReturn (*USBGetProductStringIndex)(void *, UInt8 *) * } */ - public static void USBDeviceAbortPipeZero$set(MemorySegment seg, MemorySegment x) { - constants$18.const$3.set(seg, x); - } - public static MemorySegment USBDeviceAbortPipeZero$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$18.const$3.get(seg.asSlice(index*sizeof())); - } - public static void USBDeviceAbortPipeZero$set(MemorySegment seg, long index, MemorySegment x) { - constants$18.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static USBDeviceAbortPipeZero USBDeviceAbortPipeZero(MemorySegment segment, Arena scope) { - return USBDeviceAbortPipeZero.ofAddress(USBDeviceAbortPipeZero$get(segment), scope); + public static void USBGetProductStringIndex(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBGetProductStringIndex$LAYOUT, USBGetProductStringIndex$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBGetManufacturerStringIndex)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *) * } */ - public interface USBGetManufacturerStringIndex { + public final static class USBGetSerialNumberStringIndex { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(USBGetManufacturerStringIndex fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$18.const$4, fi, constants$6.const$5, scope); + private USBGetSerialNumberStringIndex() { + // Should not be called directly } - static USBGetManufacturerStringIndex ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle USBGetManufacturerStringIndex$VH() { - return constants$18.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*USBGetManufacturerStringIndex)(void*,UInt8*); - * } - */ - public static MemorySegment USBGetManufacturerStringIndex$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$18.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBGetSerialNumberStringIndex$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBGetSerialNumberStringIndex")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBGetManufacturerStringIndex)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *) * } */ - public static void USBGetManufacturerStringIndex$set(MemorySegment seg, MemorySegment x) { - constants$18.const$5.set(seg, x); - } - public static MemorySegment USBGetManufacturerStringIndex$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$18.const$5.get(seg.asSlice(index*sizeof())); - } - public static void USBGetManufacturerStringIndex$set(MemorySegment seg, long index, MemorySegment x) { - constants$18.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static USBGetManufacturerStringIndex USBGetManufacturerStringIndex(MemorySegment segment, Arena scope) { - return USBGetManufacturerStringIndex.ofAddress(USBGetManufacturerStringIndex$get(segment), scope); + public static final AddressLayout USBGetSerialNumberStringIndex$layout() { + return USBGetSerialNumberStringIndex$LAYOUT; } + + private static final long USBGetSerialNumberStringIndex$OFFSET = $LAYOUT.byteOffset(groupElement("USBGetSerialNumberStringIndex")); + /** - * {@snippet : - * IOReturn (*USBGetProductStringIndex)(void*,UInt8*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *) * } */ - public interface USBGetProductStringIndex { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(USBGetProductStringIndex fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$19.const$0, fi, constants$6.const$5, scope); - } - static USBGetProductStringIndex ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBGetSerialNumberStringIndex$offset() { + return USBGetSerialNumberStringIndex$OFFSET; } - public static VarHandle USBGetProductStringIndex$VH() { - return constants$19.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBGetProductStringIndex)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *) * } */ - public static MemorySegment USBGetProductStringIndex$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$19.const$1.get(seg); + public static MemorySegment USBGetSerialNumberStringIndex(MemorySegment struct) { + return struct.get(USBGetSerialNumberStringIndex$LAYOUT, USBGetSerialNumberStringIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBGetProductStringIndex)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBGetSerialNumberStringIndex)(void *, UInt8 *) * } */ - public static void USBGetProductStringIndex$set(MemorySegment seg, MemorySegment x) { - constants$19.const$1.set(seg, x); - } - public static MemorySegment USBGetProductStringIndex$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$19.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBGetProductStringIndex$set(MemorySegment seg, long index, MemorySegment x) { - constants$19.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBGetProductStringIndex USBGetProductStringIndex(MemorySegment segment, Arena scope) { - return USBGetProductStringIndex.ofAddress(USBGetProductStringIndex$get(segment), scope); + public static void USBGetSerialNumberStringIndex(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBGetSerialNumberStringIndex$LAYOUT, USBGetSerialNumberStringIndex$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBGetSerialNumberStringIndex)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32) * } */ - public interface USBGetSerialNumberStringIndex { + public final static class USBDeviceReEnumerate { + + private USBDeviceReEnumerate() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(USBGetSerialNumberStringIndex fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$19.const$2, fi, constants$6.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static USBGetSerialNumberStringIndex ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, int _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle USBGetSerialNumberStringIndex$VH() { - return constants$19.const$3; - } + private static final AddressLayout USBDeviceReEnumerate$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBDeviceReEnumerate")); + /** - * Getter for field: - * {@snippet : - * IOReturn (*USBGetSerialNumberStringIndex)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32) * } */ - public static MemorySegment USBGetSerialNumberStringIndex$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$19.const$3.get(seg); + public static final AddressLayout USBDeviceReEnumerate$layout() { + return USBDeviceReEnumerate$LAYOUT; } + + private static final long USBDeviceReEnumerate$OFFSET = $LAYOUT.byteOffset(groupElement("USBDeviceReEnumerate")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBGetSerialNumberStringIndex)(void*,UInt8*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32) * } */ - public static void USBGetSerialNumberStringIndex$set(MemorySegment seg, MemorySegment x) { - constants$19.const$3.set(seg, x); - } - public static MemorySegment USBGetSerialNumberStringIndex$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$19.const$3.get(seg.asSlice(index*sizeof())); - } - public static void USBGetSerialNumberStringIndex$set(MemorySegment seg, long index, MemorySegment x) { - constants$19.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static USBGetSerialNumberStringIndex USBGetSerialNumberStringIndex(MemorySegment segment, Arena scope) { - return USBGetSerialNumberStringIndex.ofAddress(USBGetSerialNumberStringIndex$get(segment), scope); + public static final long USBDeviceReEnumerate$offset() { + return USBDeviceReEnumerate$OFFSET; } + /** - * {@snippet : - * IOReturn (*USBDeviceReEnumerate)(void*,UInt32); + * Getter for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32) * } */ - public interface USBDeviceReEnumerate { - - int apply(java.lang.foreign.MemorySegment _x0, int _x1); - static MemorySegment allocate(USBDeviceReEnumerate fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$19.const$5, fi, constants$19.const$4, scope); - } - static USBDeviceReEnumerate ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, int __x1) -> { - try { - return (int)constants$20.const$0.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static MemorySegment USBDeviceReEnumerate(MemorySegment struct) { + return struct.get(USBDeviceReEnumerate$LAYOUT, USBDeviceReEnumerate$OFFSET); } - public static VarHandle USBDeviceReEnumerate$VH() { - return constants$20.const$1; - } /** - * Getter for field: - * {@snippet : - * IOReturn (*USBDeviceReEnumerate)(void*,UInt32); + * Setter for field: + * {@snippet lang=c : + * IOReturn (*USBDeviceReEnumerate)(void *, UInt32) * } */ - public static MemorySegment USBDeviceReEnumerate$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$20.const$1.get(seg); + public static void USBDeviceReEnumerate(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBDeviceReEnumerate$LAYOUT, USBDeviceReEnumerate$OFFSET, fieldValue); } + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBDeviceReEnumerate)(void*,UInt32); - * } + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} */ - public static void USBDeviceReEnumerate$set(MemorySegment seg, MemorySegment x) { - constants$20.const$1.set(seg, x); + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static MemorySegment USBDeviceReEnumerate$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$20.const$1.get(seg.asSlice(index*sizeof())); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static void USBDeviceReEnumerate$set(MemorySegment seg, long index, MemorySegment x) { - constants$20.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static USBDeviceReEnumerate USBDeviceReEnumerate(MemorySegment segment, Arena scope) { - return USBDeviceReEnumerate.ofAddress(USBDeviceReEnumerate$get(segment), scope); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBFindInterfaceRequest.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBFindInterfaceRequest.java index 007fbbfb..e0ded3eb 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBFindInterfaceRequest.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBFindInterfaceRequest.java @@ -2,140 +2,264 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct { * UInt16 bInterfaceClass; * UInt16 bInterfaceSubClass; * UInt16 bInterfaceProtocol; * UInt16 bAlternateSetting; - * }; + * } * } */ public class IOUSBFindInterfaceRequest { - public static MemoryLayout $LAYOUT() { - return constants$1.const$2; + IOUSBFindInterfaceRequest() { + // Should not be called directly } - public static VarHandle bInterfaceClass$VH() { - return constants$1.const$3; + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_SHORT.withName("bInterfaceClass"), + IOKit.C_SHORT.withName("bInterfaceSubClass"), + IOKit.C_SHORT.withName("bInterfaceProtocol"), + IOKit.C_SHORT.withName("bAlternateSetting") + ).withName("IOUSBFindInterfaceRequest"); + + /** + * The layout of this struct + */ + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final OfShort bInterfaceClass$LAYOUT = (OfShort)$LAYOUT.select(groupElement("bInterfaceClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 bInterfaceClass + * } + */ + public static final OfShort bInterfaceClass$layout() { + return bInterfaceClass$LAYOUT; + } + + private static final long bInterfaceClass$OFFSET = $LAYOUT.byteOffset(groupElement("bInterfaceClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 bInterfaceClass + * } + */ + public static final long bInterfaceClass$offset() { + return bInterfaceClass$OFFSET; + } + /** * Getter for field: - * {@snippet : - * UInt16 bInterfaceClass; + * {@snippet lang=c : + * UInt16 bInterfaceClass * } */ - public static short bInterfaceClass$get(MemorySegment seg) { - return (short)constants$1.const$3.get(seg); + public static short bInterfaceClass(MemorySegment struct) { + return struct.get(bInterfaceClass$LAYOUT, bInterfaceClass$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 bInterfaceClass; + * {@snippet lang=c : + * UInt16 bInterfaceClass * } */ - public static void bInterfaceClass$set(MemorySegment seg, short x) { - constants$1.const$3.set(seg, x); + public static void bInterfaceClass(MemorySegment struct, short fieldValue) { + struct.set(bInterfaceClass$LAYOUT, bInterfaceClass$OFFSET, fieldValue); } - public static short bInterfaceClass$get(MemorySegment seg, long index) { - return (short)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void bInterfaceClass$set(MemorySegment seg, long index, short x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort bInterfaceSubClass$LAYOUT = (OfShort)$LAYOUT.select(groupElement("bInterfaceSubClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 bInterfaceSubClass + * } + */ + public static final OfShort bInterfaceSubClass$layout() { + return bInterfaceSubClass$LAYOUT; } - public static VarHandle bInterfaceSubClass$VH() { - return constants$1.const$4; + + private static final long bInterfaceSubClass$OFFSET = $LAYOUT.byteOffset(groupElement("bInterfaceSubClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 bInterfaceSubClass + * } + */ + public static final long bInterfaceSubClass$offset() { + return bInterfaceSubClass$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 bInterfaceSubClass; + * {@snippet lang=c : + * UInt16 bInterfaceSubClass * } */ - public static short bInterfaceSubClass$get(MemorySegment seg) { - return (short)constants$1.const$4.get(seg); + public static short bInterfaceSubClass(MemorySegment struct) { + return struct.get(bInterfaceSubClass$LAYOUT, bInterfaceSubClass$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 bInterfaceSubClass; + * {@snippet lang=c : + * UInt16 bInterfaceSubClass * } */ - public static void bInterfaceSubClass$set(MemorySegment seg, short x) { - constants$1.const$4.set(seg, x); + public static void bInterfaceSubClass(MemorySegment struct, short fieldValue) { + struct.set(bInterfaceSubClass$LAYOUT, bInterfaceSubClass$OFFSET, fieldValue); } - public static short bInterfaceSubClass$get(MemorySegment seg, long index) { - return (short)constants$1.const$4.get(seg.asSlice(index*sizeof())); - } - public static void bInterfaceSubClass$set(MemorySegment seg, long index, short x) { - constants$1.const$4.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort bInterfaceProtocol$LAYOUT = (OfShort)$LAYOUT.select(groupElement("bInterfaceProtocol")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 bInterfaceProtocol + * } + */ + public static final OfShort bInterfaceProtocol$layout() { + return bInterfaceProtocol$LAYOUT; } - public static VarHandle bInterfaceProtocol$VH() { - return constants$1.const$5; + + private static final long bInterfaceProtocol$OFFSET = $LAYOUT.byteOffset(groupElement("bInterfaceProtocol")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 bInterfaceProtocol + * } + */ + public static final long bInterfaceProtocol$offset() { + return bInterfaceProtocol$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 bInterfaceProtocol; + * {@snippet lang=c : + * UInt16 bInterfaceProtocol * } */ - public static short bInterfaceProtocol$get(MemorySegment seg) { - return (short)constants$1.const$5.get(seg); + public static short bInterfaceProtocol(MemorySegment struct) { + return struct.get(bInterfaceProtocol$LAYOUT, bInterfaceProtocol$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 bInterfaceProtocol; + * {@snippet lang=c : + * UInt16 bInterfaceProtocol * } */ - public static void bInterfaceProtocol$set(MemorySegment seg, short x) { - constants$1.const$5.set(seg, x); - } - public static short bInterfaceProtocol$get(MemorySegment seg, long index) { - return (short)constants$1.const$5.get(seg.asSlice(index*sizeof())); + public static void bInterfaceProtocol(MemorySegment struct, short fieldValue) { + struct.set(bInterfaceProtocol$LAYOUT, bInterfaceProtocol$OFFSET, fieldValue); } - public static void bInterfaceProtocol$set(MemorySegment seg, long index, short x) { - constants$1.const$5.set(seg.asSlice(index*sizeof()), x); + + private static final OfShort bAlternateSetting$LAYOUT = (OfShort)$LAYOUT.select(groupElement("bAlternateSetting")); + + /** + * Layout for field: + * {@snippet lang=c : + * UInt16 bAlternateSetting + * } + */ + public static final OfShort bAlternateSetting$layout() { + return bAlternateSetting$LAYOUT; } - public static VarHandle bAlternateSetting$VH() { - return constants$2.const$0; + + private static final long bAlternateSetting$OFFSET = $LAYOUT.byteOffset(groupElement("bAlternateSetting")); + + /** + * Offset for field: + * {@snippet lang=c : + * UInt16 bAlternateSetting + * } + */ + public static final long bAlternateSetting$offset() { + return bAlternateSetting$OFFSET; } + /** * Getter for field: - * {@snippet : - * UInt16 bAlternateSetting; + * {@snippet lang=c : + * UInt16 bAlternateSetting * } */ - public static short bAlternateSetting$get(MemorySegment seg) { - return (short)constants$2.const$0.get(seg); + public static short bAlternateSetting(MemorySegment struct) { + return struct.get(bAlternateSetting$LAYOUT, bAlternateSetting$OFFSET); } + /** * Setter for field: - * {@snippet : - * UInt16 bAlternateSetting; + * {@snippet lang=c : + * UInt16 bAlternateSetting * } */ - public static void bAlternateSetting$set(MemorySegment seg, short x) { - constants$2.const$0.set(seg, x); + public static void bAlternateSetting(MemorySegment struct, short fieldValue) { + struct.set(bAlternateSetting$LAYOUT, bAlternateSetting$OFFSET, fieldValue); + } + + /** + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} + */ + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); + } + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static short bAlternateSetting$get(MemorySegment seg, long index) { - return (short)constants$2.const$0.get(seg.asSlice(index*sizeof())); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static void bAlternateSetting$set(MemorySegment seg, long index, short x) { - constants$2.const$0.set(seg.asSlice(index*sizeof()), x); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceInterface190.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceInterface190.java deleted file mode 100644 index 44ead20b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceInterface190.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -/** - * {@snippet : - * typedef struct IOUSBInterfaceStruct190 IOUSBInterfaceInterface190; - * } - */ -public final class IOUSBInterfaceInterface190 extends IOUSBInterfaceStruct190 { - - // Suppresses default constructor, ensuring non-instantiability. - private IOUSBInterfaceInterface190() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java index 0cdc7159..f63ecf5f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/IOUSBInterfaceStruct190.java @@ -2,2648 +2,4505 @@ package net.codecrete.usb.macos.gen.iokit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + /** - * {@snippet : + * {@snippet lang=c : * struct IOUSBInterfaceStruct190 { - * void* _reserved; - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); - * ULONG (*AddRef)(void*); - * ULONG (*Release)(void*); - * IOReturn (*CreateInterfaceAsyncEventSource)(void*,CFRunLoopSourceRef*); - * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void*); - * IOReturn (*CreateInterfaceAsyncPort)(void*,mach_port_t*); - * mach_port_t (*GetInterfaceAsyncPort)(void*); - * IOReturn (*USBInterfaceOpen)(void*); - * IOReturn (*USBInterfaceClose)(void*); - * IOReturn (*GetInterfaceClass)(void*,UInt8*); - * IOReturn (*GetInterfaceSubClass)(void*,UInt8*); - * IOReturn (*GetInterfaceProtocol)(void*,UInt8*); - * IOReturn (*GetDeviceVendor)(void*,UInt16*); - * IOReturn (*GetDeviceProduct)(void*,UInt16*); - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); - * IOReturn (*GetConfigurationValue)(void*,UInt8*); - * IOReturn (*GetInterfaceNumber)(void*,UInt8*); - * IOReturn (*GetAlternateSetting)(void*,UInt8*); - * IOReturn (*GetNumEndpoints)(void*,UInt8*); - * IOReturn (*GetLocationID)(void*,UInt32*); - * IOReturn (*GetDevice)(void*,io_service_t*); - * IOReturn (*SetAlternateInterface)(void*,UInt8); - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); - * IOReturn (*ControlRequest)(void*,UInt8,IOUSBDevRequest*); - * IOReturn (*ControlRequestAsync)(void*,UInt8,IOUSBDevRequest*,IOAsyncCallback1,void*); - * IOReturn (*GetPipeProperties)(void*,UInt8,UInt8*,UInt8*,UInt8*,UInt16*,UInt8*); - * IOReturn (*GetPipeStatus)(void*,UInt8); - * IOReturn (*AbortPipe)(void*,UInt8); - * IOReturn (*ResetPipe)(void*,UInt8); - * IOReturn (*ClearPipeStall)(void*,UInt8); - * IOReturn (*ReadPipe)(void*,UInt8,void*,UInt32*); - * IOReturn (*WritePipe)(void*,UInt8,void*,UInt32); - * IOReturn (*ReadPipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); - * IOReturn (*WritePipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); - * IOReturn (*ReadIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); - * IOReturn (*WriteIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); - * IOReturn (*ControlRequestTO)(void*,UInt8,IOUSBDevRequestTO*); - * IOReturn (*ControlRequestAsyncTO)(void*,UInt8,IOUSBDevRequestTO*,IOAsyncCallback1,void*); - * IOReturn (*ReadPipeTO)(void*,UInt8,void*,UInt32*,UInt32,UInt32); - * IOReturn (*WritePipeTO)(void*,UInt8,void*,UInt32,UInt32,UInt32); - * IOReturn (*ReadPipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); - * IOReturn (*WritePipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); - * IOReturn (*USBInterfaceGetStringIndex)(void*,UInt8*); - * IOReturn (*USBInterfaceOpenSeize)(void*); - * IOReturn (*ClearPipeStallBothEnds)(void*,UInt8); - * IOReturn (*SetPipePolicy)(void*,UInt8,UInt16,UInt8); - * IOReturn (*GetBandwidthAvailable)(void*,UInt32*); - * IOReturn (*GetEndpointProperties)(void*,UInt8,UInt8,UInt8,UInt8*,UInt16*,UInt8*); - * }; + * void *_reserved; + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *); + * ULONG (*AddRef)(void *); + * ULONG (*Release)(void *); + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *); + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *); + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *); + * mach_port_t (*GetInterfaceAsyncPort)(void *); + * IOReturn (*USBInterfaceOpen)(void *); + * IOReturn (*USBInterfaceClose)(void *); + * IOReturn (*GetInterfaceClass)(void *, UInt8 *); + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *); + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *); + * IOReturn (*GetDeviceVendor)(void *, UInt16 *); + * IOReturn (*GetDeviceProduct)(void *, UInt16 *); + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *); + * IOReturn (*GetConfigurationValue)(void *, UInt8 *); + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *); + * IOReturn (*GetAlternateSetting)(void *, UInt8 *); + * IOReturn (*GetNumEndpoints)(void *, UInt8 *); + * IOReturn (*GetLocationID)(void *, UInt32 *); + * IOReturn (*GetDevice)(void *, io_service_t *); + * IOReturn (*SetAlternateInterface)(void *, UInt8); + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *); + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *); + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *); + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *); + * IOReturn (*GetPipeStatus)(void *, UInt8); + * IOReturn (*AbortPipe)(void *, UInt8); + * IOReturn (*ResetPipe)(void *, UInt8); + * IOReturn (*ClearPipeStall)(void *, UInt8); + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *); + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32); + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *); + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *); + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *); + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *); + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *); + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *); + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32); + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32); + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *); + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *); + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *); + * IOReturn (*USBInterfaceOpenSeize)(void *); + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8); + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8); + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *); + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *); + * } * } */ public class IOUSBInterfaceStruct190 { - public static MemoryLayout $LAYOUT() { - return constants$20.const$2; - } - public static VarHandle _reserved$VH() { - return constants$20.const$3; + IOUSBInterfaceStruct190() { + // Should not be called directly } + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + IOKit.C_POINTER.withName("_reserved"), + IOKit.C_POINTER.withName("QueryInterface"), + IOKit.C_POINTER.withName("AddRef"), + IOKit.C_POINTER.withName("Release"), + IOKit.C_POINTER.withName("CreateInterfaceAsyncEventSource"), + IOKit.C_POINTER.withName("GetInterfaceAsyncEventSource"), + IOKit.C_POINTER.withName("CreateInterfaceAsyncPort"), + IOKit.C_POINTER.withName("GetInterfaceAsyncPort"), + IOKit.C_POINTER.withName("USBInterfaceOpen"), + IOKit.C_POINTER.withName("USBInterfaceClose"), + IOKit.C_POINTER.withName("GetInterfaceClass"), + IOKit.C_POINTER.withName("GetInterfaceSubClass"), + IOKit.C_POINTER.withName("GetInterfaceProtocol"), + IOKit.C_POINTER.withName("GetDeviceVendor"), + IOKit.C_POINTER.withName("GetDeviceProduct"), + IOKit.C_POINTER.withName("GetDeviceReleaseNumber"), + IOKit.C_POINTER.withName("GetConfigurationValue"), + IOKit.C_POINTER.withName("GetInterfaceNumber"), + IOKit.C_POINTER.withName("GetAlternateSetting"), + IOKit.C_POINTER.withName("GetNumEndpoints"), + IOKit.C_POINTER.withName("GetLocationID"), + IOKit.C_POINTER.withName("GetDevice"), + IOKit.C_POINTER.withName("SetAlternateInterface"), + IOKit.C_POINTER.withName("GetBusFrameNumber"), + IOKit.C_POINTER.withName("ControlRequest"), + IOKit.C_POINTER.withName("ControlRequestAsync"), + IOKit.C_POINTER.withName("GetPipeProperties"), + IOKit.C_POINTER.withName("GetPipeStatus"), + IOKit.C_POINTER.withName("AbortPipe"), + IOKit.C_POINTER.withName("ResetPipe"), + IOKit.C_POINTER.withName("ClearPipeStall"), + IOKit.C_POINTER.withName("ReadPipe"), + IOKit.C_POINTER.withName("WritePipe"), + IOKit.C_POINTER.withName("ReadPipeAsync"), + IOKit.C_POINTER.withName("WritePipeAsync"), + IOKit.C_POINTER.withName("ReadIsochPipeAsync"), + IOKit.C_POINTER.withName("WriteIsochPipeAsync"), + IOKit.C_POINTER.withName("ControlRequestTO"), + IOKit.C_POINTER.withName("ControlRequestAsyncTO"), + IOKit.C_POINTER.withName("ReadPipeTO"), + IOKit.C_POINTER.withName("WritePipeTO"), + IOKit.C_POINTER.withName("ReadPipeAsyncTO"), + IOKit.C_POINTER.withName("WritePipeAsyncTO"), + IOKit.C_POINTER.withName("USBInterfaceGetStringIndex"), + IOKit.C_POINTER.withName("USBInterfaceOpenSeize"), + IOKit.C_POINTER.withName("ClearPipeStallBothEnds"), + IOKit.C_POINTER.withName("SetPipePolicy"), + IOKit.C_POINTER.withName("GetBandwidthAvailable"), + IOKit.C_POINTER.withName("GetEndpointProperties") + ).withName("IOUSBInterfaceStruct190"); + /** - * Getter for field: - * {@snippet : - * void* _reserved; - * } + * The layout of this struct */ - public static MemorySegment _reserved$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$20.const$3.get(seg); + public static final GroupLayout layout() { + return $LAYOUT; } + + private static final AddressLayout _reserved$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("_reserved")); + /** - * Setter for field: - * {@snippet : - * void* _reserved; + * Layout for field: + * {@snippet lang=c : + * void *_reserved * } */ - public static void _reserved$set(MemorySegment seg, MemorySegment x) { - constants$20.const$3.set(seg, x); - } - public static MemorySegment _reserved$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$20.const$3.get(seg.asSlice(index*sizeof())); - } - public static void _reserved$set(MemorySegment seg, long index, MemorySegment x) { - constants$20.const$3.set(seg.asSlice(index*sizeof()), x); + public static final AddressLayout _reserved$layout() { + return _reserved$LAYOUT; } + + private static final long _reserved$OFFSET = $LAYOUT.byteOffset(groupElement("_reserved")); + /** - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * Offset for field: + * {@snippet lang=c : + * void *_reserved * } */ - public interface QueryInterface { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(QueryInterface fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$20.const$4, fi, constants$5.const$1, scope); - } - static QueryInterface ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$5.const$3.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long _reserved$offset() { + return _reserved$OFFSET; } - public static VarHandle QueryInterface$VH() { - return constants$20.const$5; - } /** * Getter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * void *_reserved * } */ - public static MemorySegment QueryInterface$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$20.const$5.get(seg); + public static MemorySegment _reserved(MemorySegment struct) { + return struct.get(_reserved$LAYOUT, _reserved$OFFSET); } + /** * Setter for field: - * {@snippet : - * HRESULT (*QueryInterface)(void*,REFIID,LPVOID*); + * {@snippet lang=c : + * void *_reserved * } */ - public static void QueryInterface$set(MemorySegment seg, MemorySegment x) { - constants$20.const$5.set(seg, x); - } - public static MemorySegment QueryInterface$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$20.const$5.get(seg.asSlice(index*sizeof())); - } - public static void QueryInterface$set(MemorySegment seg, long index, MemorySegment x) { - constants$20.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static QueryInterface QueryInterface(MemorySegment segment, Arena scope) { - return QueryInterface.ofAddress(QueryInterface$get(segment), scope); + public static void _reserved(MemorySegment struct, MemorySegment fieldValue) { + struct.set(_reserved$LAYOUT, _reserved$OFFSET, fieldValue); } + /** - * {@snippet : - * ULONG (*AddRef)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public interface AddRef { + public final static class QueryInterface { - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(AddRef fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$21.const$0, fi, constants$5.const$5, scope); + private QueryInterface() { + // Should not be called directly } - static AddRef ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + CFUUIDBytes.layout(), + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle AddRef$VH() { - return constants$21.const$1; - } - /** - * Getter for field: - * {@snippet : - * ULONG (*AddRef)(void*); - * } - */ - public static MemorySegment AddRef$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$21.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout QueryInterface$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("QueryInterface")); + /** - * Setter for field: - * {@snippet : - * ULONG (*AddRef)(void*); + * Layout for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static void AddRef$set(MemorySegment seg, MemorySegment x) { - constants$21.const$1.set(seg, x); - } - public static MemorySegment AddRef$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$21.const$1.get(seg.asSlice(index*sizeof())); - } - public static void AddRef$set(MemorySegment seg, long index, MemorySegment x) { - constants$21.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static AddRef AddRef(MemorySegment segment, Arena scope) { - return AddRef.ofAddress(AddRef$get(segment), scope); + public static final AddressLayout QueryInterface$layout() { + return QueryInterface$LAYOUT; } + + private static final long QueryInterface$OFFSET = $LAYOUT.byteOffset(groupElement("QueryInterface")); + /** - * {@snippet : - * ULONG (*Release)(void*); + * Offset for field: + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public interface Release { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(Release fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$21.const$2, fi, constants$5.const$5, scope); - } - static Release ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long QueryInterface$offset() { + return QueryInterface$OFFSET; } - public static VarHandle Release$VH() { - return constants$21.const$3; - } /** * Getter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static MemorySegment Release$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$21.const$3.get(seg); + public static MemorySegment QueryInterface(MemorySegment struct) { + return struct.get(QueryInterface$LAYOUT, QueryInterface$OFFSET); } + /** * Setter for field: - * {@snippet : - * ULONG (*Release)(void*); + * {@snippet lang=c : + * HRESULT (*QueryInterface)(void *, REFIID, LPVOID *) * } */ - public static void Release$set(MemorySegment seg, MemorySegment x) { - constants$21.const$3.set(seg, x); - } - public static MemorySegment Release$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$21.const$3.get(seg.asSlice(index*sizeof())); - } - public static void Release$set(MemorySegment seg, long index, MemorySegment x) { - constants$21.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static Release Release(MemorySegment segment, Arena scope) { - return Release.ofAddress(Release$get(segment), scope); + public static void QueryInterface(MemorySegment struct, MemorySegment fieldValue) { + struct.set(QueryInterface$LAYOUT, QueryInterface$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*CreateInterfaceAsyncEventSource)(void*,CFRunLoopSourceRef*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public interface CreateInterfaceAsyncEventSource { + public final static class AddRef { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(CreateInterfaceAsyncEventSource fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$21.const$4, fi, constants$6.const$5, scope); + private AddRef() { + // Should not be called directly } - static CreateInterfaceAsyncEventSource ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle CreateInterfaceAsyncEventSource$VH() { - return constants$21.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*CreateInterfaceAsyncEventSource)(void*,CFRunLoopSourceRef*); - * } - */ - public static MemorySegment CreateInterfaceAsyncEventSource$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$21.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout AddRef$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("AddRef")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*CreateInterfaceAsyncEventSource)(void*,CFRunLoopSourceRef*); + * Layout for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static void CreateInterfaceAsyncEventSource$set(MemorySegment seg, MemorySegment x) { - constants$21.const$5.set(seg, x); - } - public static MemorySegment CreateInterfaceAsyncEventSource$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$21.const$5.get(seg.asSlice(index*sizeof())); - } - public static void CreateInterfaceAsyncEventSource$set(MemorySegment seg, long index, MemorySegment x) { - constants$21.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static CreateInterfaceAsyncEventSource CreateInterfaceAsyncEventSource(MemorySegment segment, Arena scope) { - return CreateInterfaceAsyncEventSource.ofAddress(CreateInterfaceAsyncEventSource$get(segment), scope); + public static final AddressLayout AddRef$layout() { + return AddRef$LAYOUT; } + + private static final long AddRef$OFFSET = $LAYOUT.byteOffset(groupElement("AddRef")); + /** - * {@snippet : - * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void*); + * Offset for field: + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public interface GetInterfaceAsyncEventSource { - - java.lang.foreign.MemorySegment apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(GetInterfaceAsyncEventSource fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$22.const$0, fi, constants$3.const$0, scope); - } - static GetInterfaceAsyncEventSource ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (java.lang.foreign.MemorySegment)constants$7.const$4.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long AddRef$offset() { + return AddRef$OFFSET; } - public static VarHandle GetInterfaceAsyncEventSource$VH() { - return constants$22.const$1; - } /** * Getter for field: - * {@snippet : - * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static MemorySegment GetInterfaceAsyncEventSource$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$22.const$1.get(seg); + public static MemorySegment AddRef(MemorySegment struct) { + return struct.get(AddRef$LAYOUT, AddRef$OFFSET); } + /** * Setter for field: - * {@snippet : - * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void*); + * {@snippet lang=c : + * ULONG (*AddRef)(void *) * } */ - public static void GetInterfaceAsyncEventSource$set(MemorySegment seg, MemorySegment x) { - constants$22.const$1.set(seg, x); - } - public static MemorySegment GetInterfaceAsyncEventSource$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$22.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceAsyncEventSource$set(MemorySegment seg, long index, MemorySegment x) { - constants$22.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceAsyncEventSource GetInterfaceAsyncEventSource(MemorySegment segment, Arena scope) { - return GetInterfaceAsyncEventSource.ofAddress(GetInterfaceAsyncEventSource$get(segment), scope); + public static void AddRef(MemorySegment struct, MemorySegment fieldValue) { + struct.set(AddRef$LAYOUT, AddRef$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*CreateInterfaceAsyncPort)(void*,mach_port_t*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public interface CreateInterfaceAsyncPort { + public final static class Release { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(CreateInterfaceAsyncPort fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$22.const$2, fi, constants$6.const$5, scope); + private Release() { + // Should not be called directly } - static CreateInterfaceAsyncPort ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle CreateInterfaceAsyncPort$VH() { - return constants$22.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*CreateInterfaceAsyncPort)(void*,mach_port_t*); - * } - */ - public static MemorySegment CreateInterfaceAsyncPort$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$22.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout Release$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("Release")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*CreateInterfaceAsyncPort)(void*,mach_port_t*); + * Layout for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static void CreateInterfaceAsyncPort$set(MemorySegment seg, MemorySegment x) { - constants$22.const$3.set(seg, x); - } - public static MemorySegment CreateInterfaceAsyncPort$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$22.const$3.get(seg.asSlice(index*sizeof())); - } - public static void CreateInterfaceAsyncPort$set(MemorySegment seg, long index, MemorySegment x) { - constants$22.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static CreateInterfaceAsyncPort CreateInterfaceAsyncPort(MemorySegment segment, Arena scope) { - return CreateInterfaceAsyncPort.ofAddress(CreateInterfaceAsyncPort$get(segment), scope); + public static final AddressLayout Release$layout() { + return Release$LAYOUT; } + + private static final long Release$OFFSET = $LAYOUT.byteOffset(groupElement("Release")); + /** - * {@snippet : - * mach_port_t (*GetInterfaceAsyncPort)(void*); + * Offset for field: + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public interface GetInterfaceAsyncPort { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(GetInterfaceAsyncPort fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$22.const$4, fi, constants$5.const$5, scope); - } - static GetInterfaceAsyncPort ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long Release$offset() { + return Release$OFFSET; } - public static VarHandle GetInterfaceAsyncPort$VH() { - return constants$22.const$5; - } /** * Getter for field: - * {@snippet : - * mach_port_t (*GetInterfaceAsyncPort)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static MemorySegment GetInterfaceAsyncPort$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$22.const$5.get(seg); + public static MemorySegment Release(MemorySegment struct) { + return struct.get(Release$LAYOUT, Release$OFFSET); } + /** * Setter for field: - * {@snippet : - * mach_port_t (*GetInterfaceAsyncPort)(void*); + * {@snippet lang=c : + * ULONG (*Release)(void *) * } */ - public static void GetInterfaceAsyncPort$set(MemorySegment seg, MemorySegment x) { - constants$22.const$5.set(seg, x); - } - public static MemorySegment GetInterfaceAsyncPort$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$22.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceAsyncPort$set(MemorySegment seg, long index, MemorySegment x) { - constants$22.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceAsyncPort GetInterfaceAsyncPort(MemorySegment segment, Arena scope) { - return GetInterfaceAsyncPort.ofAddress(GetInterfaceAsyncPort$get(segment), scope); + public static void Release(MemorySegment struct, MemorySegment fieldValue) { + struct.set(Release$LAYOUT, Release$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBInterfaceOpen)(void*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public interface USBInterfaceOpen { + public final static class CreateInterfaceAsyncEventSource { + + private CreateInterfaceAsyncEventSource() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBInterfaceOpen fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$23.const$0, fi, constants$5.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static USBInterfaceOpen ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle USBInterfaceOpen$VH() { - return constants$23.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*USBInterfaceOpen)(void*); - * } - */ - public static MemorySegment USBInterfaceOpen$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$23.const$1.get(seg); - } + private static final AddressLayout CreateInterfaceAsyncEventSource$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("CreateInterfaceAsyncEventSource")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBInterfaceOpen)(void*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static void USBInterfaceOpen$set(MemorySegment seg, MemorySegment x) { - constants$23.const$1.set(seg, x); - } - public static MemorySegment USBInterfaceOpen$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$23.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBInterfaceOpen$set(MemorySegment seg, long index, MemorySegment x) { - constants$23.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBInterfaceOpen USBInterfaceOpen(MemorySegment segment, Arena scope) { - return USBInterfaceOpen.ofAddress(USBInterfaceOpen$get(segment), scope); + public static final AddressLayout CreateInterfaceAsyncEventSource$layout() { + return CreateInterfaceAsyncEventSource$LAYOUT; } + + private static final long CreateInterfaceAsyncEventSource$OFFSET = $LAYOUT.byteOffset(groupElement("CreateInterfaceAsyncEventSource")); + /** - * {@snippet : - * IOReturn (*USBInterfaceClose)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public interface USBInterfaceClose { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBInterfaceClose fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$23.const$2, fi, constants$5.const$5, scope); - } - static USBInterfaceClose ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long CreateInterfaceAsyncEventSource$offset() { + return CreateInterfaceAsyncEventSource$OFFSET; } - public static VarHandle USBInterfaceClose$VH() { - return constants$23.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBInterfaceClose)(void*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static MemorySegment USBInterfaceClose$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$23.const$3.get(seg); + public static MemorySegment CreateInterfaceAsyncEventSource(MemorySegment struct) { + return struct.get(CreateInterfaceAsyncEventSource$LAYOUT, CreateInterfaceAsyncEventSource$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBInterfaceClose)(void*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncEventSource)(void *, CFRunLoopSourceRef *) * } */ - public static void USBInterfaceClose$set(MemorySegment seg, MemorySegment x) { - constants$23.const$3.set(seg, x); - } - public static MemorySegment USBInterfaceClose$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$23.const$3.get(seg.asSlice(index*sizeof())); - } - public static void USBInterfaceClose$set(MemorySegment seg, long index, MemorySegment x) { - constants$23.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static USBInterfaceClose USBInterfaceClose(MemorySegment segment, Arena scope) { - return USBInterfaceClose.ofAddress(USBInterfaceClose$get(segment), scope); + public static void CreateInterfaceAsyncEventSource(MemorySegment struct, MemorySegment fieldValue) { + struct.set(CreateInterfaceAsyncEventSource$LAYOUT, CreateInterfaceAsyncEventSource$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetInterfaceClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *) * } */ - public interface GetInterfaceClass { + public final static class GetInterfaceAsyncEventSource { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetInterfaceClass fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$23.const$4, fi, constants$6.const$5, scope); + private GetInterfaceAsyncEventSource() { + // Should not be called directly } - static GetInterfaceClass ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetInterfaceClass$VH() { - return constants$23.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetInterfaceClass)(void*,UInt8*); - * } - */ - public static MemorySegment GetInterfaceClass$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$23.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static MemorySegment invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (MemorySegment) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout GetInterfaceAsyncEventSource$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceAsyncEventSource")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetInterfaceClass)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *) * } */ - public static void GetInterfaceClass$set(MemorySegment seg, MemorySegment x) { - constants$23.const$5.set(seg, x); - } - public static MemorySegment GetInterfaceClass$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$23.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceClass$set(MemorySegment seg, long index, MemorySegment x) { - constants$23.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceClass GetInterfaceClass(MemorySegment segment, Arena scope) { - return GetInterfaceClass.ofAddress(GetInterfaceClass$get(segment), scope); + public static final AddressLayout GetInterfaceAsyncEventSource$layout() { + return GetInterfaceAsyncEventSource$LAYOUT; } + + private static final long GetInterfaceAsyncEventSource$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceAsyncEventSource")); + /** - * {@snippet : - * IOReturn (*GetInterfaceSubClass)(void*,UInt8*); + * Offset for field: + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *) * } */ - public interface GetInterfaceSubClass { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetInterfaceSubClass fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$24.const$0, fi, constants$6.const$5, scope); - } - static GetInterfaceSubClass ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long GetInterfaceAsyncEventSource$offset() { + return GetInterfaceAsyncEventSource$OFFSET; } - public static VarHandle GetInterfaceSubClass$VH() { - return constants$24.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetInterfaceSubClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *) * } */ - public static MemorySegment GetInterfaceSubClass$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$24.const$1.get(seg); + public static MemorySegment GetInterfaceAsyncEventSource(MemorySegment struct) { + return struct.get(GetInterfaceAsyncEventSource$LAYOUT, GetInterfaceAsyncEventSource$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetInterfaceSubClass)(void*,UInt8*); + * {@snippet lang=c : + * CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *) * } */ - public static void GetInterfaceSubClass$set(MemorySegment seg, MemorySegment x) { - constants$24.const$1.set(seg, x); - } - public static MemorySegment GetInterfaceSubClass$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$24.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceSubClass$set(MemorySegment seg, long index, MemorySegment x) { - constants$24.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceSubClass GetInterfaceSubClass(MemorySegment segment, Arena scope) { - return GetInterfaceSubClass.ofAddress(GetInterfaceSubClass$get(segment), scope); + public static void GetInterfaceAsyncEventSource(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceAsyncEventSource$LAYOUT, GetInterfaceAsyncEventSource$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetInterfaceProtocol)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *) * } */ - public interface GetInterfaceProtocol { + public final static class CreateInterfaceAsyncPort { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetInterfaceProtocol fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$24.const$2, fi, constants$6.const$5, scope); + private CreateInterfaceAsyncPort() { + // Should not be called directly } - static GetInterfaceProtocol ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetInterfaceProtocol$VH() { - return constants$24.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetInterfaceProtocol)(void*,UInt8*); - * } - */ - public static MemorySegment GetInterfaceProtocol$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$24.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout CreateInterfaceAsyncPort$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("CreateInterfaceAsyncPort")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetInterfaceProtocol)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *) * } */ - public static void GetInterfaceProtocol$set(MemorySegment seg, MemorySegment x) { - constants$24.const$3.set(seg, x); - } - public static MemorySegment GetInterfaceProtocol$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$24.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceProtocol$set(MemorySegment seg, long index, MemorySegment x) { - constants$24.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceProtocol GetInterfaceProtocol(MemorySegment segment, Arena scope) { - return GetInterfaceProtocol.ofAddress(GetInterfaceProtocol$get(segment), scope); + public static final AddressLayout CreateInterfaceAsyncPort$layout() { + return CreateInterfaceAsyncPort$LAYOUT; } + + private static final long CreateInterfaceAsyncPort$OFFSET = $LAYOUT.byteOffset(groupElement("CreateInterfaceAsyncPort")); + /** - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *) * } */ - public interface GetDeviceVendor { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceVendor fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$24.const$4, fi, constants$6.const$5, scope); - } - static GetDeviceVendor ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long CreateInterfaceAsyncPort$offset() { + return CreateInterfaceAsyncPort$OFFSET; } - public static VarHandle GetDeviceVendor$VH() { - return constants$24.const$5; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *) * } */ - public static MemorySegment GetDeviceVendor$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$24.const$5.get(seg); + public static MemorySegment CreateInterfaceAsyncPort(MemorySegment struct) { + return struct.get(CreateInterfaceAsyncPort$LAYOUT, CreateInterfaceAsyncPort$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceVendor)(void*,UInt16*); + * {@snippet lang=c : + * IOReturn (*CreateInterfaceAsyncPort)(void *, mach_port_t *) * } */ - public static void GetDeviceVendor$set(MemorySegment seg, MemorySegment x) { - constants$24.const$5.set(seg, x); - } - public static MemorySegment GetDeviceVendor$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$24.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceVendor$set(MemorySegment seg, long index, MemorySegment x) { - constants$24.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceVendor GetDeviceVendor(MemorySegment segment, Arena scope) { - return GetDeviceVendor.ofAddress(GetDeviceVendor$get(segment), scope); + public static void CreateInterfaceAsyncPort(MemorySegment struct, MemorySegment fieldValue) { + struct.set(CreateInterfaceAsyncPort$LAYOUT, CreateInterfaceAsyncPort$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetInterfaceAsyncPort)(void *) * } */ - public interface GetDeviceProduct { + public final static class GetInterfaceAsyncPort { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceProduct fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$25.const$0, fi, constants$6.const$5, scope); + private GetInterfaceAsyncPort() { + // Should not be called directly } - static GetDeviceProduct ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDeviceProduct$VH() { - return constants$25.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); - * } - */ - public static MemorySegment GetDeviceProduct$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$25.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout GetInterfaceAsyncPort$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceAsyncPort")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceProduct)(void*,UInt16*); + * Layout for field: + * {@snippet lang=c : + * mach_port_t (*GetInterfaceAsyncPort)(void *) * } */ - public static void GetDeviceProduct$set(MemorySegment seg, MemorySegment x) { - constants$25.const$1.set(seg, x); - } - public static MemorySegment GetDeviceProduct$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$25.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceProduct$set(MemorySegment seg, long index, MemorySegment x) { - constants$25.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceProduct GetDeviceProduct(MemorySegment segment, Arena scope) { - return GetDeviceProduct.ofAddress(GetDeviceProduct$get(segment), scope); + public static final AddressLayout GetInterfaceAsyncPort$layout() { + return GetInterfaceAsyncPort$LAYOUT; } + + private static final long GetInterfaceAsyncPort$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceAsyncPort")); + /** - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * Offset for field: + * {@snippet lang=c : + * mach_port_t (*GetInterfaceAsyncPort)(void *) * } */ - public interface GetDeviceReleaseNumber { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDeviceReleaseNumber fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$25.const$2, fi, constants$6.const$5, scope); - } - static GetDeviceReleaseNumber ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long GetInterfaceAsyncPort$offset() { + return GetInterfaceAsyncPort$OFFSET; } - public static VarHandle GetDeviceReleaseNumber$VH() { - return constants$25.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetInterfaceAsyncPort)(void *) * } */ - public static MemorySegment GetDeviceReleaseNumber$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$25.const$3.get(seg); + public static MemorySegment GetInterfaceAsyncPort(MemorySegment struct) { + return struct.get(GetInterfaceAsyncPort$LAYOUT, GetInterfaceAsyncPort$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetDeviceReleaseNumber)(void*,UInt16*); + * {@snippet lang=c : + * mach_port_t (*GetInterfaceAsyncPort)(void *) * } */ - public static void GetDeviceReleaseNumber$set(MemorySegment seg, MemorySegment x) { - constants$25.const$3.set(seg, x); - } - public static MemorySegment GetDeviceReleaseNumber$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$25.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDeviceReleaseNumber$set(MemorySegment seg, long index, MemorySegment x) { - constants$25.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDeviceReleaseNumber GetDeviceReleaseNumber(MemorySegment segment, Arena scope) { - return GetDeviceReleaseNumber.ofAddress(GetDeviceReleaseNumber$get(segment), scope); + public static void GetInterfaceAsyncPort(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceAsyncPort$LAYOUT, GetInterfaceAsyncPort$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetConfigurationValue)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpen)(void *) * } */ - public interface GetConfigurationValue { + public final static class USBInterfaceOpen { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetConfigurationValue fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$25.const$4, fi, constants$6.const$5, scope); + private USBInterfaceOpen() { + // Should not be called directly } - static GetConfigurationValue ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetConfigurationValue$VH() { - return constants$25.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetConfigurationValue)(void*,UInt8*); - * } - */ - public static MemorySegment GetConfigurationValue$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$25.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBInterfaceOpen$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBInterfaceOpen")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetConfigurationValue)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpen)(void *) * } */ - public static void GetConfigurationValue$set(MemorySegment seg, MemorySegment x) { - constants$25.const$5.set(seg, x); - } - public static MemorySegment GetConfigurationValue$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$25.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetConfigurationValue$set(MemorySegment seg, long index, MemorySegment x) { - constants$25.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetConfigurationValue GetConfigurationValue(MemorySegment segment, Arena scope) { - return GetConfigurationValue.ofAddress(GetConfigurationValue$get(segment), scope); + public static final AddressLayout USBInterfaceOpen$layout() { + return USBInterfaceOpen$LAYOUT; } + + private static final long USBInterfaceOpen$OFFSET = $LAYOUT.byteOffset(groupElement("USBInterfaceOpen")); + /** - * {@snippet : - * IOReturn (*GetInterfaceNumber)(void*,UInt8*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpen)(void *) * } */ - public interface GetInterfaceNumber { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetInterfaceNumber fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$26.const$0, fi, constants$6.const$5, scope); - } - static GetInterfaceNumber ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBInterfaceOpen$offset() { + return USBInterfaceOpen$OFFSET; } - public static VarHandle GetInterfaceNumber$VH() { - return constants$26.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetInterfaceNumber)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpen)(void *) * } */ - public static MemorySegment GetInterfaceNumber$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$26.const$1.get(seg); + public static MemorySegment USBInterfaceOpen(MemorySegment struct) { + return struct.get(USBInterfaceOpen$LAYOUT, USBInterfaceOpen$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetInterfaceNumber)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpen)(void *) * } */ - public static void GetInterfaceNumber$set(MemorySegment seg, MemorySegment x) { - constants$26.const$1.set(seg, x); - } - public static MemorySegment GetInterfaceNumber$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$26.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetInterfaceNumber$set(MemorySegment seg, long index, MemorySegment x) { - constants$26.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetInterfaceNumber GetInterfaceNumber(MemorySegment segment, Arena scope) { - return GetInterfaceNumber.ofAddress(GetInterfaceNumber$get(segment), scope); + public static void USBInterfaceOpen(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBInterfaceOpen$LAYOUT, USBInterfaceOpen$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetAlternateSetting)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceClose)(void *) * } */ - public interface GetAlternateSetting { + public final static class USBInterfaceClose { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetAlternateSetting fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$26.const$2, fi, constants$6.const$5, scope); + private USBInterfaceClose() { + // Should not be called directly } - static GetAlternateSetting ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout USBInterfaceClose$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBInterfaceClose")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceClose)(void *) + * } + */ + public static final AddressLayout USBInterfaceClose$layout() { + return USBInterfaceClose$LAYOUT; + } + + private static final long USBInterfaceClose$OFFSET = $LAYOUT.byteOffset(groupElement("USBInterfaceClose")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceClose)(void *) + * } + */ + public static final long USBInterfaceClose$offset() { + return USBInterfaceClose$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceClose)(void *) + * } + */ + public static MemorySegment USBInterfaceClose(MemorySegment struct) { + return struct.get(USBInterfaceClose$LAYOUT, USBInterfaceClose$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceClose)(void *) + * } + */ + public static void USBInterfaceClose(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBInterfaceClose$LAYOUT, USBInterfaceClose$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetInterfaceClass)(void *, UInt8 *) + * } + */ + public final static class GetInterfaceClass { + + private GetInterfaceClass() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetInterfaceClass$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceClass)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetInterfaceClass$layout() { + return GetInterfaceClass$LAYOUT; + } + + private static final long GetInterfaceClass$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceClass)(void *, UInt8 *) + * } + */ + public static final long GetInterfaceClass$offset() { + return GetInterfaceClass$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceClass)(void *, UInt8 *) + * } + */ + public static MemorySegment GetInterfaceClass(MemorySegment struct) { + return struct.get(GetInterfaceClass$LAYOUT, GetInterfaceClass$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceClass)(void *, UInt8 *) + * } + */ + public static void GetInterfaceClass(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceClass$LAYOUT, GetInterfaceClass$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *) + * } + */ + public final static class GetInterfaceSubClass { + + private GetInterfaceSubClass() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetInterfaceSubClass$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceSubClass")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetInterfaceSubClass$layout() { + return GetInterfaceSubClass$LAYOUT; + } + + private static final long GetInterfaceSubClass$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceSubClass")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *) + * } + */ + public static final long GetInterfaceSubClass$offset() { + return GetInterfaceSubClass$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *) + * } + */ + public static MemorySegment GetInterfaceSubClass(MemorySegment struct) { + return struct.get(GetInterfaceSubClass$LAYOUT, GetInterfaceSubClass$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceSubClass)(void *, UInt8 *) + * } + */ + public static void GetInterfaceSubClass(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceSubClass$LAYOUT, GetInterfaceSubClass$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *) + * } + */ + public final static class GetInterfaceProtocol { + + private GetInterfaceProtocol() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetInterfaceProtocol$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceProtocol")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetInterfaceProtocol$layout() { + return GetInterfaceProtocol$LAYOUT; + } + + private static final long GetInterfaceProtocol$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceProtocol")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *) + * } + */ + public static final long GetInterfaceProtocol$offset() { + return GetInterfaceProtocol$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *) + * } + */ + public static MemorySegment GetInterfaceProtocol(MemorySegment struct) { + return struct.get(GetInterfaceProtocol$LAYOUT, GetInterfaceProtocol$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceProtocol)(void *, UInt8 *) + * } + */ + public static void GetInterfaceProtocol(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceProtocol$LAYOUT, GetInterfaceProtocol$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public final static class GetDeviceVendor { + + private GetDeviceVendor() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceVendor$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceVendor")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceVendor$layout() { + return GetDeviceVendor$LAYOUT; + } + + private static final long GetDeviceVendor$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceVendor")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static final long GetDeviceVendor$offset() { + return GetDeviceVendor$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceVendor(MemorySegment struct) { + return struct.get(GetDeviceVendor$LAYOUT, GetDeviceVendor$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceVendor)(void *, UInt16 *) + * } + */ + public static void GetDeviceVendor(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceVendor$LAYOUT, GetDeviceVendor$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public final static class GetDeviceProduct { + + private GetDeviceProduct() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceProduct$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceProduct")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceProduct$layout() { + return GetDeviceProduct$LAYOUT; + } + + private static final long GetDeviceProduct$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceProduct")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static final long GetDeviceProduct$offset() { + return GetDeviceProduct$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceProduct(MemorySegment struct) { + return struct.get(GetDeviceProduct$LAYOUT, GetDeviceProduct$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceProduct)(void *, UInt16 *) + * } + */ + public static void GetDeviceProduct(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceProduct$LAYOUT, GetDeviceProduct$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public final static class GetDeviceReleaseNumber { + + private GetDeviceReleaseNumber() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDeviceReleaseNumber$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDeviceReleaseNumber")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static final AddressLayout GetDeviceReleaseNumber$layout() { + return GetDeviceReleaseNumber$LAYOUT; + } + + private static final long GetDeviceReleaseNumber$OFFSET = $LAYOUT.byteOffset(groupElement("GetDeviceReleaseNumber")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static final long GetDeviceReleaseNumber$offset() { + return GetDeviceReleaseNumber$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static MemorySegment GetDeviceReleaseNumber(MemorySegment struct) { + return struct.get(GetDeviceReleaseNumber$LAYOUT, GetDeviceReleaseNumber$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDeviceReleaseNumber)(void *, UInt16 *) + * } + */ + public static void GetDeviceReleaseNumber(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDeviceReleaseNumber$LAYOUT, GetDeviceReleaseNumber$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetConfigurationValue)(void *, UInt8 *) + * } + */ + public final static class GetConfigurationValue { + + private GetConfigurationValue() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetConfigurationValue$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetConfigurationValue")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationValue)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetConfigurationValue$layout() { + return GetConfigurationValue$LAYOUT; + } + + private static final long GetConfigurationValue$OFFSET = $LAYOUT.byteOffset(groupElement("GetConfigurationValue")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationValue)(void *, UInt8 *) + * } + */ + public static final long GetConfigurationValue$offset() { + return GetConfigurationValue$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationValue)(void *, UInt8 *) + * } + */ + public static MemorySegment GetConfigurationValue(MemorySegment struct) { + return struct.get(GetConfigurationValue$LAYOUT, GetConfigurationValue$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetConfigurationValue)(void *, UInt8 *) + * } + */ + public static void GetConfigurationValue(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetConfigurationValue$LAYOUT, GetConfigurationValue$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *) + * } + */ + public final static class GetInterfaceNumber { + + private GetInterfaceNumber() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetInterfaceNumber$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetInterfaceNumber")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetInterfaceNumber$layout() { + return GetInterfaceNumber$LAYOUT; + } + + private static final long GetInterfaceNumber$OFFSET = $LAYOUT.byteOffset(groupElement("GetInterfaceNumber")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *) + * } + */ + public static final long GetInterfaceNumber$offset() { + return GetInterfaceNumber$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *) + * } + */ + public static MemorySegment GetInterfaceNumber(MemorySegment struct) { + return struct.get(GetInterfaceNumber$LAYOUT, GetInterfaceNumber$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetInterfaceNumber)(void *, UInt8 *) + * } + */ + public static void GetInterfaceNumber(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetInterfaceNumber$LAYOUT, GetInterfaceNumber$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetAlternateSetting)(void *, UInt8 *) + * } + */ + public final static class GetAlternateSetting { + + private GetAlternateSetting() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetAlternateSetting$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetAlternateSetting")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetAlternateSetting)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetAlternateSetting$layout() { + return GetAlternateSetting$LAYOUT; + } + + private static final long GetAlternateSetting$OFFSET = $LAYOUT.byteOffset(groupElement("GetAlternateSetting")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetAlternateSetting)(void *, UInt8 *) + * } + */ + public static final long GetAlternateSetting$offset() { + return GetAlternateSetting$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetAlternateSetting)(void *, UInt8 *) + * } + */ + public static MemorySegment GetAlternateSetting(MemorySegment struct) { + return struct.get(GetAlternateSetting$LAYOUT, GetAlternateSetting$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetAlternateSetting)(void *, UInt8 *) + * } + */ + public static void GetAlternateSetting(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetAlternateSetting$LAYOUT, GetAlternateSetting$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetNumEndpoints)(void *, UInt8 *) + * } + */ + public final static class GetNumEndpoints { + + private GetNumEndpoints() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetNumEndpoints$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetNumEndpoints")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetNumEndpoints)(void *, UInt8 *) + * } + */ + public static final AddressLayout GetNumEndpoints$layout() { + return GetNumEndpoints$LAYOUT; + } + + private static final long GetNumEndpoints$OFFSET = $LAYOUT.byteOffset(groupElement("GetNumEndpoints")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetNumEndpoints)(void *, UInt8 *) + * } + */ + public static final long GetNumEndpoints$offset() { + return GetNumEndpoints$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetNumEndpoints)(void *, UInt8 *) + * } + */ + public static MemorySegment GetNumEndpoints(MemorySegment struct) { + return struct.get(GetNumEndpoints$LAYOUT, GetNumEndpoints$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetNumEndpoints)(void *, UInt8 *) + * } + */ + public static void GetNumEndpoints(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetNumEndpoints$LAYOUT, GetNumEndpoints$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public final static class GetLocationID { + + private GetLocationID() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetLocationID$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetLocationID")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static final AddressLayout GetLocationID$layout() { + return GetLocationID$LAYOUT; + } + + private static final long GetLocationID$OFFSET = $LAYOUT.byteOffset(groupElement("GetLocationID")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static final long GetLocationID$offset() { + return GetLocationID$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static MemorySegment GetLocationID(MemorySegment struct) { + return struct.get(GetLocationID$LAYOUT, GetLocationID$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetLocationID)(void *, UInt32 *) + * } + */ + public static void GetLocationID(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetLocationID$LAYOUT, GetLocationID$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetDevice)(void *, io_service_t *) + * } + */ + public final static class GetDevice { + + private GetDevice() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetDevice$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetDevice")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetDevice)(void *, io_service_t *) + * } + */ + public static final AddressLayout GetDevice$layout() { + return GetDevice$LAYOUT; + } + + private static final long GetDevice$OFFSET = $LAYOUT.byteOffset(groupElement("GetDevice")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetDevice)(void *, io_service_t *) + * } + */ + public static final long GetDevice$offset() { + return GetDevice$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetDevice)(void *, io_service_t *) + * } + */ + public static MemorySegment GetDevice(MemorySegment struct) { + return struct.get(GetDevice$LAYOUT, GetDevice$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetDevice)(void *, io_service_t *) + * } + */ + public static void GetDevice(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetDevice$LAYOUT, GetDevice$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*SetAlternateInterface)(void *, UInt8) + * } + */ + public final static class SetAlternateInterface { + + private SetAlternateInterface() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout SetAlternateInterface$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("SetAlternateInterface")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*SetAlternateInterface)(void *, UInt8) + * } + */ + public static final AddressLayout SetAlternateInterface$layout() { + return SetAlternateInterface$LAYOUT; + } + + private static final long SetAlternateInterface$OFFSET = $LAYOUT.byteOffset(groupElement("SetAlternateInterface")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*SetAlternateInterface)(void *, UInt8) + * } + */ + public static final long SetAlternateInterface$offset() { + return SetAlternateInterface$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*SetAlternateInterface)(void *, UInt8) + * } + */ + public static MemorySegment SetAlternateInterface(MemorySegment struct) { + return struct.get(SetAlternateInterface$LAYOUT, SetAlternateInterface$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*SetAlternateInterface)(void *, UInt8) + * } + */ + public static void SetAlternateInterface(MemorySegment struct, MemorySegment fieldValue) { + struct.set(SetAlternateInterface$LAYOUT, SetAlternateInterface$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public final static class GetBusFrameNumber { + + private GetBusFrameNumber() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetBusFrameNumber$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetBusFrameNumber")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static final AddressLayout GetBusFrameNumber$layout() { + return GetBusFrameNumber$LAYOUT; + } + + private static final long GetBusFrameNumber$OFFSET = $LAYOUT.byteOffset(groupElement("GetBusFrameNumber")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static final long GetBusFrameNumber$offset() { + return GetBusFrameNumber$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static MemorySegment GetBusFrameNumber(MemorySegment struct) { + return struct.get(GetBusFrameNumber$LAYOUT, GetBusFrameNumber$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetBusFrameNumber)(void *, UInt64 *, AbsoluteTime *) + * } + */ + public static void GetBusFrameNumber(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetBusFrameNumber$LAYOUT, GetBusFrameNumber$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *) + * } + */ + public final static class ControlRequest { + + private ControlRequest() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout ControlRequest$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ControlRequest")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *) + * } + */ + public static final AddressLayout ControlRequest$layout() { + return ControlRequest$LAYOUT; + } + + private static final long ControlRequest$OFFSET = $LAYOUT.byteOffset(groupElement("ControlRequest")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *) + * } + */ + public static final long ControlRequest$offset() { + return ControlRequest$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *) + * } + */ + public static MemorySegment ControlRequest(MemorySegment struct) { + return struct.get(ControlRequest$LAYOUT, ControlRequest$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*ControlRequest)(void *, UInt8, IOUSBDevRequest *) + * } + */ + public static void ControlRequest(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ControlRequest$LAYOUT, ControlRequest$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public final static class ControlRequestAsync { + + private ControlRequestAsync() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, MemorySegment _x3, MemorySegment _x4) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout ControlRequestAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ControlRequestAsync")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout ControlRequestAsync$layout() { + return ControlRequestAsync$LAYOUT; + } + + private static final long ControlRequestAsync$OFFSET = $LAYOUT.byteOffset(groupElement("ControlRequestAsync")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static final long ControlRequestAsync$offset() { + return ControlRequestAsync$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static MemorySegment ControlRequestAsync(MemorySegment struct) { + return struct.get(ControlRequestAsync$LAYOUT, ControlRequestAsync$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsync)(void *, UInt8, IOUSBDevRequest *, IOAsyncCallback1, void *) + * } + */ + public static void ControlRequestAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ControlRequestAsync$LAYOUT, ControlRequestAsync$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *) + * } + */ + public final static class GetPipeProperties { + + private GetPipeProperties() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, MemorySegment _x3, MemorySegment _x4, MemorySegment _x5, MemorySegment _x6) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetPipeProperties$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetPipeProperties")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *) + * } + */ + public static final AddressLayout GetPipeProperties$layout() { + return GetPipeProperties$LAYOUT; + } + + private static final long GetPipeProperties$OFFSET = $LAYOUT.byteOffset(groupElement("GetPipeProperties")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *) + * } + */ + public static final long GetPipeProperties$offset() { + return GetPipeProperties$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *) + * } + */ + public static MemorySegment GetPipeProperties(MemorySegment struct) { + return struct.get(GetPipeProperties$LAYOUT, GetPipeProperties$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetPipeProperties)(void *, UInt8, UInt8 *, UInt8 *, UInt8 *, UInt16 *, UInt8 *) + * } + */ + public static void GetPipeProperties(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetPipeProperties$LAYOUT, GetPipeProperties$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*GetPipeStatus)(void *, UInt8) + * } + */ + public final static class GetPipeStatus { + + private GetPipeStatus() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout GetPipeStatus$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetPipeStatus")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetPipeStatus)(void *, UInt8) + * } + */ + public static final AddressLayout GetPipeStatus$layout() { + return GetPipeStatus$LAYOUT; + } + + private static final long GetPipeStatus$OFFSET = $LAYOUT.byteOffset(groupElement("GetPipeStatus")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetPipeStatus)(void *, UInt8) + * } + */ + public static final long GetPipeStatus$offset() { + return GetPipeStatus$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetPipeStatus)(void *, UInt8) + * } + */ + public static MemorySegment GetPipeStatus(MemorySegment struct) { + return struct.get(GetPipeStatus$LAYOUT, GetPipeStatus$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetPipeStatus)(void *, UInt8) + * } + */ + public static void GetPipeStatus(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetPipeStatus$LAYOUT, GetPipeStatus$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*AbortPipe)(void *, UInt8) + * } + */ + public final static class AbortPipe { + + private AbortPipe() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout AbortPipe$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("AbortPipe")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*AbortPipe)(void *, UInt8) + * } + */ + public static final AddressLayout AbortPipe$layout() { + return AbortPipe$LAYOUT; + } + + private static final long AbortPipe$OFFSET = $LAYOUT.byteOffset(groupElement("AbortPipe")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*AbortPipe)(void *, UInt8) + * } + */ + public static final long AbortPipe$offset() { + return AbortPipe$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*AbortPipe)(void *, UInt8) + * } + */ + public static MemorySegment AbortPipe(MemorySegment struct) { + return struct.get(AbortPipe$LAYOUT, AbortPipe$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*AbortPipe)(void *, UInt8) + * } + */ + public static void AbortPipe(MemorySegment struct, MemorySegment fieldValue) { + struct.set(AbortPipe$LAYOUT, AbortPipe$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*ResetPipe)(void *, UInt8) + * } + */ + public final static class ResetPipe { + + private ResetPipe() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout ResetPipe$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ResetPipe")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ResetPipe)(void *, UInt8) + * } + */ + public static final AddressLayout ResetPipe$layout() { + return ResetPipe$LAYOUT; + } + + private static final long ResetPipe$OFFSET = $LAYOUT.byteOffset(groupElement("ResetPipe")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ResetPipe)(void *, UInt8) + * } + */ + public static final long ResetPipe$offset() { + return ResetPipe$OFFSET; + } + + /** + * Getter for field: + * {@snippet lang=c : + * IOReturn (*ResetPipe)(void *, UInt8) + * } + */ + public static MemorySegment ResetPipe(MemorySegment struct) { + return struct.get(ResetPipe$LAYOUT, ResetPipe$OFFSET); + } + + /** + * Setter for field: + * {@snippet lang=c : + * IOReturn (*ResetPipe)(void *, UInt8) + * } + */ + public static void ResetPipe(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ResetPipe$LAYOUT, ResetPipe$OFFSET, fieldValue); + } + + /** + * {@snippet lang=c : + * IOReturn (*ClearPipeStall)(void *, UInt8) + * } + */ + public final static class ClearPipeStall { + + private ClearPipeStall() { + // Should not be called directly + } + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + + private static final AddressLayout ClearPipeStall$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ClearPipeStall")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ClearPipeStall)(void *, UInt8) + * } + */ + public static final AddressLayout ClearPipeStall$layout() { + return ClearPipeStall$LAYOUT; } - public static VarHandle GetAlternateSetting$VH() { - return constants$26.const$3; + private static final long ClearPipeStall$OFFSET = $LAYOUT.byteOffset(groupElement("ClearPipeStall")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ClearPipeStall)(void *, UInt8) + * } + */ + public static final long ClearPipeStall$offset() { + return ClearPipeStall$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetAlternateSetting)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ClearPipeStall)(void *, UInt8) * } */ - public static MemorySegment GetAlternateSetting$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$26.const$3.get(seg); + public static MemorySegment ClearPipeStall(MemorySegment struct) { + return struct.get(ClearPipeStall$LAYOUT, ClearPipeStall$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetAlternateSetting)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ClearPipeStall)(void *, UInt8) * } */ - public static void GetAlternateSetting$set(MemorySegment seg, MemorySegment x) { - constants$26.const$3.set(seg, x); - } - public static MemorySegment GetAlternateSetting$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$26.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetAlternateSetting$set(MemorySegment seg, long index, MemorySegment x) { - constants$26.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetAlternateSetting GetAlternateSetting(MemorySegment segment, Arena scope) { - return GetAlternateSetting.ofAddress(GetAlternateSetting$get(segment), scope); + public static void ClearPipeStall(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ClearPipeStall$LAYOUT, ClearPipeStall$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetNumEndpoints)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *) * } */ - public interface GetNumEndpoints { + public final static class ReadPipe { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetNumEndpoints fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$26.const$4, fi, constants$6.const$5, scope); + private ReadPipe() { + // Should not be called directly } - static GetNumEndpoints ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetNumEndpoints$VH() { - return constants$26.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetNumEndpoints)(void*,UInt8*); - * } - */ - public static MemorySegment GetNumEndpoints$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$26.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, MemorySegment _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout ReadPipe$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ReadPipe")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetNumEndpoints)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *) * } */ - public static void GetNumEndpoints$set(MemorySegment seg, MemorySegment x) { - constants$26.const$5.set(seg, x); - } - public static MemorySegment GetNumEndpoints$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$26.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetNumEndpoints$set(MemorySegment seg, long index, MemorySegment x) { - constants$26.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetNumEndpoints GetNumEndpoints(MemorySegment segment, Arena scope) { - return GetNumEndpoints.ofAddress(GetNumEndpoints$get(segment), scope); + public static final AddressLayout ReadPipe$layout() { + return ReadPipe$LAYOUT; } + + private static final long ReadPipe$OFFSET = $LAYOUT.byteOffset(groupElement("ReadPipe")); + /** - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *) * } */ - public interface GetLocationID { - - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetLocationID fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$27.const$0, fi, constants$6.const$5, scope); - } - static GetLocationID ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long ReadPipe$offset() { + return ReadPipe$OFFSET; } - public static VarHandle GetLocationID$VH() { - return constants$27.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *) * } */ - public static MemorySegment GetLocationID$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$27.const$1.get(seg); + public static MemorySegment ReadPipe(MemorySegment struct) { + return struct.get(ReadPipe$LAYOUT, ReadPipe$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetLocationID)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*ReadPipe)(void *, UInt8, void *, UInt32 *) * } */ - public static void GetLocationID$set(MemorySegment seg, MemorySegment x) { - constants$27.const$1.set(seg, x); - } - public static MemorySegment GetLocationID$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$27.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetLocationID$set(MemorySegment seg, long index, MemorySegment x) { - constants$27.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetLocationID GetLocationID(MemorySegment segment, Arena scope) { - return GetLocationID.ofAddress(GetLocationID$get(segment), scope); + public static void ReadPipe(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ReadPipe$LAYOUT, ReadPipe$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetDevice)(void*,io_service_t*); + * {@snippet lang=c : + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32) * } */ - public interface GetDevice { + public final static class WritePipe { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetDevice fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$27.const$2, fi, constants$6.const$5, scope); + private WritePipe() { + // Should not be called directly } - static GetDevice ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetDevice$VH() { - return constants$27.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetDevice)(void*,io_service_t*); - * } - */ - public static MemorySegment GetDevice$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$27.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout WritePipe$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("WritePipe")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetDevice)(void*,io_service_t*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32) * } */ - public static void GetDevice$set(MemorySegment seg, MemorySegment x) { - constants$27.const$3.set(seg, x); - } - public static MemorySegment GetDevice$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$27.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetDevice$set(MemorySegment seg, long index, MemorySegment x) { - constants$27.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetDevice GetDevice(MemorySegment segment, Arena scope) { - return GetDevice.ofAddress(GetDevice$get(segment), scope); + public static final AddressLayout WritePipe$layout() { + return WritePipe$LAYOUT; } + + private static final long WritePipe$OFFSET = $LAYOUT.byteOffset(groupElement("WritePipe")); + /** - * {@snippet : - * IOReturn (*SetAlternateInterface)(void*,UInt8); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32) * } */ - public interface SetAlternateInterface { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(SetAlternateInterface fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$27.const$4, fi, constants$14.const$0, scope); - } - static SetAlternateInterface ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long WritePipe$offset() { + return WritePipe$OFFSET; } - public static VarHandle SetAlternateInterface$VH() { - return constants$27.const$5; - } /** * Getter for field: - * {@snippet : - * IOReturn (*SetAlternateInterface)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32) * } */ - public static MemorySegment SetAlternateInterface$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$27.const$5.get(seg); + public static MemorySegment WritePipe(MemorySegment struct) { + return struct.get(WritePipe$LAYOUT, WritePipe$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*SetAlternateInterface)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*WritePipe)(void *, UInt8, void *, UInt32) * } */ - public static void SetAlternateInterface$set(MemorySegment seg, MemorySegment x) { - constants$27.const$5.set(seg, x); - } - public static MemorySegment SetAlternateInterface$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$27.const$5.get(seg.asSlice(index*sizeof())); - } - public static void SetAlternateInterface$set(MemorySegment seg, long index, MemorySegment x) { - constants$27.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static SetAlternateInterface SetAlternateInterface(MemorySegment segment, Arena scope) { - return SetAlternateInterface.ofAddress(SetAlternateInterface$get(segment), scope); + public static void WritePipe(MemorySegment struct, MemorySegment fieldValue) { + struct.set(WritePipe$LAYOUT, WritePipe$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public interface GetBusFrameNumber { + public final static class ReadPipeAsync { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(GetBusFrameNumber fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$28.const$0, fi, constants$14.const$4, scope); + private ReadPipeAsync() { + // Should not be called directly } - static GetBusFrameNumber ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$15.const$0.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle GetBusFrameNumber$VH() { - return constants$28.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); - * } - */ - public static MemorySegment GetBusFrameNumber$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$28.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3, MemorySegment _x4, MemorySegment _x5) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout ReadPipeAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ReadPipeAsync")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetBusFrameNumber)(void*,UInt64*,AbsoluteTime*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public static void GetBusFrameNumber$set(MemorySegment seg, MemorySegment x) { - constants$28.const$1.set(seg, x); - } - public static MemorySegment GetBusFrameNumber$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$28.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetBusFrameNumber$set(MemorySegment seg, long index, MemorySegment x) { - constants$28.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetBusFrameNumber GetBusFrameNumber(MemorySegment segment, Arena scope) { - return GetBusFrameNumber.ofAddress(GetBusFrameNumber$get(segment), scope); + public static final AddressLayout ReadPipeAsync$layout() { + return ReadPipeAsync$LAYOUT; } + + private static final long ReadPipeAsync$OFFSET = $LAYOUT.byteOffset(groupElement("ReadPipeAsync")); + /** - * {@snippet : - * IOReturn (*ControlRequest)(void*,UInt8,IOUSBDevRequest*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public interface ControlRequest { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(ControlRequest fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$28.const$2, fi, constants$13.const$0, scope); - } - static ControlRequest ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$13.const$2.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long ReadPipeAsync$offset() { + return ReadPipeAsync$OFFSET; } - public static VarHandle ControlRequest$VH() { - return constants$28.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*ControlRequest)(void*,UInt8,IOUSBDevRequest*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public static MemorySegment ControlRequest$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$28.const$3.get(seg); + public static MemorySegment ReadPipeAsync(MemorySegment struct) { + return struct.get(ReadPipeAsync$LAYOUT, ReadPipeAsync$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ControlRequest)(void*,UInt8,IOUSBDevRequest*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public static void ControlRequest$set(MemorySegment seg, MemorySegment x) { - constants$28.const$3.set(seg, x); - } - public static MemorySegment ControlRequest$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$28.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ControlRequest$set(MemorySegment seg, long index, MemorySegment x) { - constants$28.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static ControlRequest ControlRequest(MemorySegment segment, Arena scope) { - return ControlRequest.ofAddress(ControlRequest$get(segment), scope); + public static void ReadPipeAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ReadPipeAsync$LAYOUT, ReadPipeAsync$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ControlRequestAsync)(void*,UInt8,IOUSBDevRequest*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public interface ControlRequestAsync { + public final static class WritePipeAsync { + + private WritePipeAsync() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3, java.lang.foreign.MemorySegment _x4); - static MemorySegment allocate(ControlRequestAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$28.const$5, fi, constants$28.const$4, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static ControlRequestAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3, java.lang.foreign.MemorySegment __x4) -> { - try { - return (int)constants$29.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3, MemorySegment _x4, MemorySegment _x5) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle ControlRequestAsync$VH() { - return constants$29.const$1; + private static final AddressLayout WritePipeAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("WritePipeAsync")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout WritePipeAsync$layout() { + return WritePipeAsync$LAYOUT; + } + + private static final long WritePipeAsync$OFFSET = $LAYOUT.byteOffset(groupElement("WritePipeAsync")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) + * } + */ + public static final long WritePipeAsync$offset() { + return WritePipeAsync$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*ControlRequestAsync)(void*,UInt8,IOUSBDevRequest*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public static MemorySegment ControlRequestAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$29.const$1.get(seg); + public static MemorySegment WritePipeAsync(MemorySegment struct) { + return struct.get(WritePipeAsync$LAYOUT, WritePipeAsync$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ControlRequestAsync)(void*,UInt8,IOUSBDevRequest*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsync)(void *, UInt8, void *, UInt32, IOAsyncCallback1, void *) * } */ - public static void ControlRequestAsync$set(MemorySegment seg, MemorySegment x) { - constants$29.const$1.set(seg, x); - } - public static MemorySegment ControlRequestAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$29.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ControlRequestAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$29.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ControlRequestAsync ControlRequestAsync(MemorySegment segment, Arena scope) { - return ControlRequestAsync.ofAddress(ControlRequestAsync$get(segment), scope); + public static void WritePipeAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(WritePipeAsync$LAYOUT, WritePipeAsync$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetPipeProperties)(void*,UInt8,UInt8*,UInt8*,UInt8*,UInt16*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public interface GetPipeProperties { + public final static class ReadIsochPipeAsync { + + private ReadIsochPipeAsync() { + // Should not be called directly + } - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3, java.lang.foreign.MemorySegment _x4, java.lang.foreign.MemorySegment _x5, java.lang.foreign.MemorySegment _x6); - static MemorySegment allocate(GetPipeProperties fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$29.const$3, fi, constants$29.const$2, scope); + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_LONG_LONG, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static GetPipeProperties ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3, java.lang.foreign.MemorySegment __x4, java.lang.foreign.MemorySegment __x5, java.lang.foreign.MemorySegment __x6) -> { - try { - return (int)constants$29.const$4.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, long _x3, int _x4, MemorySegment _x5, MemorySegment _x6, MemorySegment _x7) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetPipeProperties$VH() { - return constants$29.const$5; + private static final AddressLayout ReadIsochPipeAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ReadIsochPipeAsync")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout ReadIsochPipeAsync$layout() { + return ReadIsochPipeAsync$LAYOUT; + } + + private static final long ReadIsochPipeAsync$OFFSET = $LAYOUT.byteOffset(groupElement("ReadIsochPipeAsync")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) + * } + */ + public static final long ReadIsochPipeAsync$offset() { + return ReadIsochPipeAsync$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetPipeProperties)(void*,UInt8,UInt8*,UInt8*,UInt8*,UInt16*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public static MemorySegment GetPipeProperties$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$29.const$5.get(seg); + public static MemorySegment ReadIsochPipeAsync(MemorySegment struct) { + return struct.get(ReadIsochPipeAsync$LAYOUT, ReadIsochPipeAsync$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetPipeProperties)(void*,UInt8,UInt8*,UInt8*,UInt8*,UInt16*,UInt8*); + * {@snippet lang=c : + * IOReturn (*ReadIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public static void GetPipeProperties$set(MemorySegment seg, MemorySegment x) { - constants$29.const$5.set(seg, x); - } - public static MemorySegment GetPipeProperties$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$29.const$5.get(seg.asSlice(index*sizeof())); - } - public static void GetPipeProperties$set(MemorySegment seg, long index, MemorySegment x) { - constants$29.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static GetPipeProperties GetPipeProperties(MemorySegment segment, Arena scope) { - return GetPipeProperties.ofAddress(GetPipeProperties$get(segment), scope); + public static void ReadIsochPipeAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ReadIsochPipeAsync$LAYOUT, ReadIsochPipeAsync$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetPipeStatus)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public interface GetPipeStatus { + public final static class WriteIsochPipeAsync { + + private WriteIsochPipeAsync() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(GetPipeStatus fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$30.const$0, fi, constants$14.const$0, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_LONG_LONG, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static GetPipeStatus ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, long _x3, int _x4, MemorySegment _x5, MemorySegment _x6, MemorySegment _x7) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetPipeStatus$VH() { - return constants$30.const$1; + private static final AddressLayout WriteIsochPipeAsync$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("WriteIsochPipeAsync")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout WriteIsochPipeAsync$layout() { + return WriteIsochPipeAsync$LAYOUT; + } + + private static final long WriteIsochPipeAsync$OFFSET = $LAYOUT.byteOffset(groupElement("WriteIsochPipeAsync")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) + * } + */ + public static final long WriteIsochPipeAsync$offset() { + return WriteIsochPipeAsync$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*GetPipeStatus)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public static MemorySegment GetPipeStatus$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$30.const$1.get(seg); + public static MemorySegment WriteIsochPipeAsync(MemorySegment struct) { + return struct.get(WriteIsochPipeAsync$LAYOUT, WriteIsochPipeAsync$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*GetPipeStatus)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*WriteIsochPipeAsync)(void *, UInt8, void *, UInt64, UInt32, IOUSBIsocFrame *, IOAsyncCallback1, void *) * } */ - public static void GetPipeStatus$set(MemorySegment seg, MemorySegment x) { - constants$30.const$1.set(seg, x); - } - public static MemorySegment GetPipeStatus$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$30.const$1.get(seg.asSlice(index*sizeof())); - } - public static void GetPipeStatus$set(MemorySegment seg, long index, MemorySegment x) { - constants$30.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static GetPipeStatus GetPipeStatus(MemorySegment segment, Arena scope) { - return GetPipeStatus.ofAddress(GetPipeStatus$get(segment), scope); + public static void WriteIsochPipeAsync(MemorySegment struct, MemorySegment fieldValue) { + struct.set(WriteIsochPipeAsync$LAYOUT, WriteIsochPipeAsync$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*AbortPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *) * } */ - public interface AbortPipe { + public final static class ControlRequestTO { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(AbortPipe fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$30.const$2, fi, constants$14.const$0, scope); + private ControlRequestTO() { + // Should not be called directly } - static AbortPipe ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; + } + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle AbortPipe$VH() { - return constants$30.const$3; + private static final AddressLayout ControlRequestTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ControlRequestTO")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *) + * } + */ + public static final AddressLayout ControlRequestTO$layout() { + return ControlRequestTO$LAYOUT; + } + + private static final long ControlRequestTO$OFFSET = $LAYOUT.byteOffset(groupElement("ControlRequestTO")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *) + * } + */ + public static final long ControlRequestTO$offset() { + return ControlRequestTO$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*AbortPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *) * } */ - public static MemorySegment AbortPipe$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$30.const$3.get(seg); + public static MemorySegment ControlRequestTO(MemorySegment struct) { + return struct.get(ControlRequestTO$LAYOUT, ControlRequestTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*AbortPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestTO)(void *, UInt8, IOUSBDevRequestTO *) * } */ - public static void AbortPipe$set(MemorySegment seg, MemorySegment x) { - constants$30.const$3.set(seg, x); - } - public static MemorySegment AbortPipe$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$30.const$3.get(seg.asSlice(index*sizeof())); - } - public static void AbortPipe$set(MemorySegment seg, long index, MemorySegment x) { - constants$30.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static AbortPipe AbortPipe(MemorySegment segment, Arena scope) { - return AbortPipe.ofAddress(AbortPipe$get(segment), scope); + public static void ControlRequestTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ControlRequestTO$LAYOUT, ControlRequestTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ResetPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public interface ResetPipe { + public final static class ControlRequestAsyncTO { + + private ControlRequestAsyncTO() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(ResetPipe fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$30.const$4, fi, constants$14.const$0, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static ResetPipe ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, MemorySegment _x3, MemorySegment _x4) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle ResetPipe$VH() { - return constants$30.const$5; + private static final AddressLayout ControlRequestAsyncTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ControlRequestAsyncTO")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *) + * } + */ + public static final AddressLayout ControlRequestAsyncTO$layout() { + return ControlRequestAsyncTO$LAYOUT; + } + + private static final long ControlRequestAsyncTO$OFFSET = $LAYOUT.byteOffset(groupElement("ControlRequestAsyncTO")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *) + * } + */ + public static final long ControlRequestAsyncTO$offset() { + return ControlRequestAsyncTO$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*ResetPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public static MemorySegment ResetPipe$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$30.const$5.get(seg); + public static MemorySegment ControlRequestAsyncTO(MemorySegment struct) { + return struct.get(ControlRequestAsyncTO$LAYOUT, ControlRequestAsyncTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ResetPipe)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ControlRequestAsyncTO)(void *, UInt8, IOUSBDevRequestTO *, IOAsyncCallback1, void *) * } */ - public static void ResetPipe$set(MemorySegment seg, MemorySegment x) { - constants$30.const$5.set(seg, x); - } - public static MemorySegment ResetPipe$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$30.const$5.get(seg.asSlice(index*sizeof())); - } - public static void ResetPipe$set(MemorySegment seg, long index, MemorySegment x) { - constants$30.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static ResetPipe ResetPipe(MemorySegment segment, Arena scope) { - return ResetPipe.ofAddress(ResetPipe$get(segment), scope); + public static void ControlRequestAsyncTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ControlRequestAsyncTO$LAYOUT, ControlRequestAsyncTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ClearPipeStall)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32) * } */ - public interface ClearPipeStall { + public final static class ReadPipeTO { + + private ReadPipeTO() { + // Should not be called directly + } - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(ClearPipeStall fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$31.const$0, fi, constants$14.const$0, scope); + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static ClearPipeStall ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, MemorySegment _x3, int _x4, int _x5) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle ClearPipeStall$VH() { - return constants$31.const$1; + private static final AddressLayout ReadPipeTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ReadPipeTO")); + + /** + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32) + * } + */ + public static final AddressLayout ReadPipeTO$layout() { + return ReadPipeTO$LAYOUT; + } + + private static final long ReadPipeTO$OFFSET = $LAYOUT.byteOffset(groupElement("ReadPipeTO")); + + /** + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32) + * } + */ + public static final long ReadPipeTO$offset() { + return ReadPipeTO$OFFSET; } + /** * Getter for field: - * {@snippet : - * IOReturn (*ClearPipeStall)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32) * } */ - public static MemorySegment ClearPipeStall$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$31.const$1.get(seg); + public static MemorySegment ReadPipeTO(MemorySegment struct) { + return struct.get(ReadPipeTO$LAYOUT, ReadPipeTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ClearPipeStall)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*ReadPipeTO)(void *, UInt8, void *, UInt32 *, UInt32, UInt32) * } */ - public static void ClearPipeStall$set(MemorySegment seg, MemorySegment x) { - constants$31.const$1.set(seg, x); - } - public static MemorySegment ClearPipeStall$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$31.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ClearPipeStall$set(MemorySegment seg, long index, MemorySegment x) { - constants$31.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ClearPipeStall ClearPipeStall(MemorySegment segment, Arena scope) { - return ClearPipeStall.ofAddress(ClearPipeStall$get(segment), scope); + public static void ReadPipeTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ReadPipeTO$LAYOUT, ReadPipeTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ReadPipe)(void*,UInt8,void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32) * } */ - public interface ReadPipe { + public final static class WritePipeTO { + + private WritePipeTO() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3); - static MemorySegment allocate(ReadPipe fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$31.const$3, fi, constants$31.const$2, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_INT + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static ReadPipe ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3) -> { - try { - return (int)constants$31.const$4.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3, int _x4, int _x5) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle ReadPipe$VH() { - return constants$31.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ReadPipe)(void*,UInt8,void*,UInt32*); - * } - */ - public static MemorySegment ReadPipe$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$31.const$5.get(seg); - } + private static final AddressLayout WritePipeTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("WritePipeTO")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ReadPipe)(void*,UInt8,void*,UInt32*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32) * } */ - public static void ReadPipe$set(MemorySegment seg, MemorySegment x) { - constants$31.const$5.set(seg, x); - } - public static MemorySegment ReadPipe$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$31.const$5.get(seg.asSlice(index*sizeof())); - } - public static void ReadPipe$set(MemorySegment seg, long index, MemorySegment x) { - constants$31.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static ReadPipe ReadPipe(MemorySegment segment, Arena scope) { - return ReadPipe.ofAddress(ReadPipe$get(segment), scope); + public static final AddressLayout WritePipeTO$layout() { + return WritePipeTO$LAYOUT; } + + private static final long WritePipeTO$OFFSET = $LAYOUT.byteOffset(groupElement("WritePipeTO")); + /** - * {@snippet : - * IOReturn (*WritePipe)(void*,UInt8,void*,UInt32); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32) * } */ - public interface WritePipe { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3); - static MemorySegment allocate(WritePipe fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$32.const$1, fi, constants$32.const$0, scope); - } - static WritePipe ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3) -> { - try { - return (int)constants$32.const$2.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long WritePipeTO$offset() { + return WritePipeTO$OFFSET; } - public static VarHandle WritePipe$VH() { - return constants$32.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*WritePipe)(void*,UInt8,void*,UInt32); + * {@snippet lang=c : + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32) * } */ - public static MemorySegment WritePipe$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$32.const$3.get(seg); + public static MemorySegment WritePipeTO(MemorySegment struct) { + return struct.get(WritePipeTO$LAYOUT, WritePipeTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*WritePipe)(void*,UInt8,void*,UInt32); + * {@snippet lang=c : + * IOReturn (*WritePipeTO)(void *, UInt8, void *, UInt32, UInt32, UInt32) * } */ - public static void WritePipe$set(MemorySegment seg, MemorySegment x) { - constants$32.const$3.set(seg, x); - } - public static MemorySegment WritePipe$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$32.const$3.get(seg.asSlice(index*sizeof())); - } - public static void WritePipe$set(MemorySegment seg, long index, MemorySegment x) { - constants$32.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static WritePipe WritePipe(MemorySegment segment, Arena scope) { - return WritePipe.ofAddress(WritePipe$get(segment), scope); + public static void WritePipeTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(WritePipeTO$LAYOUT, WritePipeTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ReadPipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public interface ReadPipeAsync { + public final static class ReadPipeAsyncTO { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3, java.lang.foreign.MemorySegment _x4, java.lang.foreign.MemorySegment _x5); - static MemorySegment allocate(ReadPipeAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$32.const$5, fi, constants$32.const$4, scope); + private ReadPipeAsyncTO() { + // Should not be called directly } - static ReadPipeAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3, java.lang.foreign.MemorySegment __x4, java.lang.foreign.MemorySegment __x5) -> { - try { - return (int)constants$33.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle ReadPipeAsync$VH() { - return constants$33.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ReadPipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); - * } - */ - public static MemorySegment ReadPipeAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$33.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3, int _x4, int _x5, MemorySegment _x6, MemorySegment _x7) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout ReadPipeAsyncTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ReadPipeAsyncTO")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ReadPipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static void ReadPipeAsync$set(MemorySegment seg, MemorySegment x) { - constants$33.const$1.set(seg, x); - } - public static MemorySegment ReadPipeAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$33.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ReadPipeAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$33.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ReadPipeAsync ReadPipeAsync(MemorySegment segment, Arena scope) { - return ReadPipeAsync.ofAddress(ReadPipeAsync$get(segment), scope); + public static final AddressLayout ReadPipeAsyncTO$layout() { + return ReadPipeAsyncTO$LAYOUT; } + + private static final long ReadPipeAsyncTO$OFFSET = $LAYOUT.byteOffset(groupElement("ReadPipeAsyncTO")); + /** - * {@snippet : - * IOReturn (*WritePipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public interface WritePipeAsync { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3, java.lang.foreign.MemorySegment _x4, java.lang.foreign.MemorySegment _x5); - static MemorySegment allocate(WritePipeAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$33.const$2, fi, constants$32.const$4, scope); - } - static WritePipeAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3, java.lang.foreign.MemorySegment __x4, java.lang.foreign.MemorySegment __x5) -> { - try { - return (int)constants$33.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long ReadPipeAsyncTO$offset() { + return ReadPipeAsyncTO$OFFSET; } - public static VarHandle WritePipeAsync$VH() { - return constants$33.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*WritePipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static MemorySegment WritePipeAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$33.const$3.get(seg); + public static MemorySegment ReadPipeAsyncTO(MemorySegment struct) { + return struct.get(ReadPipeAsyncTO$LAYOUT, ReadPipeAsyncTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*WritePipeAsync)(void*,UInt8,void*,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ReadPipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static void WritePipeAsync$set(MemorySegment seg, MemorySegment x) { - constants$33.const$3.set(seg, x); - } - public static MemorySegment WritePipeAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$33.const$3.get(seg.asSlice(index*sizeof())); - } - public static void WritePipeAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$33.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static WritePipeAsync WritePipeAsync(MemorySegment segment, Arena scope) { - return WritePipeAsync.ofAddress(WritePipeAsync$get(segment), scope); + public static void ReadPipeAsyncTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ReadPipeAsyncTO$LAYOUT, ReadPipeAsyncTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ReadIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public interface ReadIsochPipeAsync { + public final static class WritePipeAsyncTO { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, long _x3, int _x4, java.lang.foreign.MemorySegment _x5, java.lang.foreign.MemorySegment _x6, java.lang.foreign.MemorySegment _x7); - static MemorySegment allocate(ReadIsochPipeAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$33.const$5, fi, constants$33.const$4, scope); + private WritePipeAsyncTO() { + // Should not be called directly } - static ReadIsochPipeAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, long __x3, int __x4, java.lang.foreign.MemorySegment __x5, java.lang.foreign.MemorySegment __x6, java.lang.foreign.MemorySegment __x7) -> { - try { - return (int)constants$34.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6, __x7); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle ReadIsochPipeAsync$VH() { - return constants$34.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ReadIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); - * } - */ - public static MemorySegment ReadIsochPipeAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$34.const$1.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, MemorySegment _x2, int _x3, int _x4, int _x5, MemorySegment _x6, MemorySegment _x7) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout WritePipeAsyncTO$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("WritePipeAsyncTO")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ReadIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static void ReadIsochPipeAsync$set(MemorySegment seg, MemorySegment x) { - constants$34.const$1.set(seg, x); - } - public static MemorySegment ReadIsochPipeAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$34.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ReadIsochPipeAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$34.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ReadIsochPipeAsync ReadIsochPipeAsync(MemorySegment segment, Arena scope) { - return ReadIsochPipeAsync.ofAddress(ReadIsochPipeAsync$get(segment), scope); + public static final AddressLayout WritePipeAsyncTO$layout() { + return WritePipeAsyncTO$LAYOUT; } + + private static final long WritePipeAsyncTO$OFFSET = $LAYOUT.byteOffset(groupElement("WritePipeAsyncTO")); + /** - * {@snippet : - * IOReturn (*WriteIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public interface WriteIsochPipeAsync { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, long _x3, int _x4, java.lang.foreign.MemorySegment _x5, java.lang.foreign.MemorySegment _x6, java.lang.foreign.MemorySegment _x7); - static MemorySegment allocate(WriteIsochPipeAsync fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$34.const$2, fi, constants$33.const$4, scope); - } - static WriteIsochPipeAsync ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, long __x3, int __x4, java.lang.foreign.MemorySegment __x5, java.lang.foreign.MemorySegment __x6, java.lang.foreign.MemorySegment __x7) -> { - try { - return (int)constants$34.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6, __x7); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long WritePipeAsyncTO$offset() { + return WritePipeAsyncTO$OFFSET; } - public static VarHandle WriteIsochPipeAsync$VH() { - return constants$34.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*WriteIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static MemorySegment WriteIsochPipeAsync$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$34.const$3.get(seg); + public static MemorySegment WritePipeAsyncTO(MemorySegment struct) { + return struct.get(WritePipeAsyncTO$LAYOUT, WritePipeAsyncTO$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*WriteIsochPipeAsync)(void*,UInt8,void*,UInt64,UInt32,IOUSBIsocFrame*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*WritePipeAsyncTO)(void *, UInt8, void *, UInt32, UInt32, UInt32, IOAsyncCallback1, void *) * } */ - public static void WriteIsochPipeAsync$set(MemorySegment seg, MemorySegment x) { - constants$34.const$3.set(seg, x); - } - public static MemorySegment WriteIsochPipeAsync$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$34.const$3.get(seg.asSlice(index*sizeof())); - } - public static void WriteIsochPipeAsync$set(MemorySegment seg, long index, MemorySegment x) { - constants$34.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static WriteIsochPipeAsync WriteIsochPipeAsync(MemorySegment segment, Arena scope) { - return WriteIsochPipeAsync.ofAddress(WriteIsochPipeAsync$get(segment), scope); + public static void WritePipeAsyncTO(MemorySegment struct, MemorySegment fieldValue) { + struct.set(WritePipeAsyncTO$LAYOUT, WritePipeAsyncTO$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ControlRequestTO)(void*,UInt8,IOUSBDevRequestTO*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *) * } */ - public interface ControlRequestTO { + public final static class USBInterfaceGetStringIndex { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2); - static MemorySegment allocate(ControlRequestTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$34.const$4, fi, constants$13.const$0, scope); + private USBInterfaceGetStringIndex() { + // Should not be called directly } - static ControlRequestTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2) -> { - try { - return (int)constants$13.const$2.invokeExact(symbol, __x0, __x1, __x2); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle ControlRequestTO$VH() { - return constants$34.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ControlRequestTO)(void*,UInt8,IOUSBDevRequestTO*); - * } - */ - public static MemorySegment ControlRequestTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$34.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBInterfaceGetStringIndex$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBInterfaceGetStringIndex")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ControlRequestTO)(void*,UInt8,IOUSBDevRequestTO*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *) * } */ - public static void ControlRequestTO$set(MemorySegment seg, MemorySegment x) { - constants$34.const$5.set(seg, x); - } - public static MemorySegment ControlRequestTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$34.const$5.get(seg.asSlice(index*sizeof())); - } - public static void ControlRequestTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$34.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static ControlRequestTO ControlRequestTO(MemorySegment segment, Arena scope) { - return ControlRequestTO.ofAddress(ControlRequestTO$get(segment), scope); + public static final AddressLayout USBInterfaceGetStringIndex$layout() { + return USBInterfaceGetStringIndex$LAYOUT; } + + private static final long USBInterfaceGetStringIndex$OFFSET = $LAYOUT.byteOffset(groupElement("USBInterfaceGetStringIndex")); + /** - * {@snippet : - * IOReturn (*ControlRequestAsyncTO)(void*,UInt8,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *) * } */ - public interface ControlRequestAsyncTO { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3, java.lang.foreign.MemorySegment _x4); - static MemorySegment allocate(ControlRequestAsyncTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$35.const$0, fi, constants$28.const$4, scope); - } - static ControlRequestAsyncTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3, java.lang.foreign.MemorySegment __x4) -> { - try { - return (int)constants$29.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBInterfaceGetStringIndex$offset() { + return USBInterfaceGetStringIndex$OFFSET; } - public static VarHandle ControlRequestAsyncTO$VH() { - return constants$35.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*ControlRequestAsyncTO)(void*,UInt8,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *) * } */ - public static MemorySegment ControlRequestAsyncTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$35.const$1.get(seg); + public static MemorySegment USBInterfaceGetStringIndex(MemorySegment struct) { + return struct.get(USBInterfaceGetStringIndex$LAYOUT, USBInterfaceGetStringIndex$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*ControlRequestAsyncTO)(void*,UInt8,IOUSBDevRequestTO*,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*USBInterfaceGetStringIndex)(void *, UInt8 *) * } */ - public static void ControlRequestAsyncTO$set(MemorySegment seg, MemorySegment x) { - constants$35.const$1.set(seg, x); - } - public static MemorySegment ControlRequestAsyncTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$35.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ControlRequestAsyncTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$35.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ControlRequestAsyncTO ControlRequestAsyncTO(MemorySegment segment, Arena scope) { - return ControlRequestAsyncTO.ofAddress(ControlRequestAsyncTO$get(segment), scope); + public static void USBInterfaceGetStringIndex(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBInterfaceGetStringIndex$LAYOUT, USBInterfaceGetStringIndex$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ReadPipeTO)(void*,UInt8,void*,UInt32*,UInt32,UInt32); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpenSeize)(void *) * } */ - public interface ReadPipeTO { + public final static class USBInterfaceOpenSeize { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, java.lang.foreign.MemorySegment _x3, int _x4, int _x5); - static MemorySegment allocate(ReadPipeTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$35.const$3, fi, constants$35.const$2, scope); + private USBInterfaceOpenSeize() { + // Should not be called directly } - static ReadPipeTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, java.lang.foreign.MemorySegment __x3, int __x4, int __x5) -> { - try { - return (int)constants$35.const$4.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle ReadPipeTO$VH() { - return constants$35.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ReadPipeTO)(void*,UInt8,void*,UInt32*,UInt32,UInt32); - * } - */ - public static MemorySegment ReadPipeTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$35.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout USBInterfaceOpenSeize$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("USBInterfaceOpenSeize")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ReadPipeTO)(void*,UInt8,void*,UInt32*,UInt32,UInt32); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpenSeize)(void *) * } */ - public static void ReadPipeTO$set(MemorySegment seg, MemorySegment x) { - constants$35.const$5.set(seg, x); - } - public static MemorySegment ReadPipeTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$35.const$5.get(seg.asSlice(index*sizeof())); - } - public static void ReadPipeTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$35.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static ReadPipeTO ReadPipeTO(MemorySegment segment, Arena scope) { - return ReadPipeTO.ofAddress(ReadPipeTO$get(segment), scope); + public static final AddressLayout USBInterfaceOpenSeize$layout() { + return USBInterfaceOpenSeize$LAYOUT; } + + private static final long USBInterfaceOpenSeize$OFFSET = $LAYOUT.byteOffset(groupElement("USBInterfaceOpenSeize")); + /** - * {@snippet : - * IOReturn (*WritePipeTO)(void*,UInt8,void*,UInt32,UInt32,UInt32); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpenSeize)(void *) * } */ - public interface WritePipeTO { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3, int _x4, int _x5); - static MemorySegment allocate(WritePipeTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$36.const$1, fi, constants$36.const$0, scope); - } - static WritePipeTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3, int __x4, int __x5) -> { - try { - return (int)constants$36.const$2.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long USBInterfaceOpenSeize$offset() { + return USBInterfaceOpenSeize$OFFSET; } - public static VarHandle WritePipeTO$VH() { - return constants$36.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*WritePipeTO)(void*,UInt8,void*,UInt32,UInt32,UInt32); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpenSeize)(void *) * } */ - public static MemorySegment WritePipeTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$36.const$3.get(seg); + public static MemorySegment USBInterfaceOpenSeize(MemorySegment struct) { + return struct.get(USBInterfaceOpenSeize$LAYOUT, USBInterfaceOpenSeize$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*WritePipeTO)(void*,UInt8,void*,UInt32,UInt32,UInt32); + * {@snippet lang=c : + * IOReturn (*USBInterfaceOpenSeize)(void *) * } */ - public static void WritePipeTO$set(MemorySegment seg, MemorySegment x) { - constants$36.const$3.set(seg, x); - } - public static MemorySegment WritePipeTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$36.const$3.get(seg.asSlice(index*sizeof())); - } - public static void WritePipeTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$36.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static WritePipeTO WritePipeTO(MemorySegment segment, Arena scope) { - return WritePipeTO.ofAddress(WritePipeTO$get(segment), scope); + public static void USBInterfaceOpenSeize(MemorySegment struct, MemorySegment fieldValue) { + struct.set(USBInterfaceOpenSeize$LAYOUT, USBInterfaceOpenSeize$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ReadPipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8) * } */ - public interface ReadPipeAsyncTO { + public final static class ClearPipeStallBothEnds { + + private ClearPipeStallBothEnds() { + // Should not be called directly + } - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3, int _x4, int _x5, java.lang.foreign.MemorySegment _x6, java.lang.foreign.MemorySegment _x7); - static MemorySegment allocate(ReadPipeAsyncTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$36.const$5, fi, constants$36.const$4, scope); + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static ReadPipeAsyncTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3, int __x4, int __x5, java.lang.foreign.MemorySegment __x6, java.lang.foreign.MemorySegment __x7) -> { - try { - return (int)constants$37.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6, __x7); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle ReadPipeAsyncTO$VH() { - return constants$37.const$1; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ReadPipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); - * } - */ - public static MemorySegment ReadPipeAsyncTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$37.const$1.get(seg); - } + private static final AddressLayout ClearPipeStallBothEnds$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("ClearPipeStallBothEnds")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ReadPipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8) * } */ - public static void ReadPipeAsyncTO$set(MemorySegment seg, MemorySegment x) { - constants$37.const$1.set(seg, x); - } - public static MemorySegment ReadPipeAsyncTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$37.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ReadPipeAsyncTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$37.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static ReadPipeAsyncTO ReadPipeAsyncTO(MemorySegment segment, Arena scope) { - return ReadPipeAsyncTO.ofAddress(ReadPipeAsyncTO$get(segment), scope); + public static final AddressLayout ClearPipeStallBothEnds$layout() { + return ClearPipeStallBothEnds$LAYOUT; } + + private static final long ClearPipeStallBothEnds$OFFSET = $LAYOUT.byteOffset(groupElement("ClearPipeStallBothEnds")); + /** - * {@snippet : - * IOReturn (*WritePipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8) * } */ - public interface WritePipeAsyncTO { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, java.lang.foreign.MemorySegment _x2, int _x3, int _x4, int _x5, java.lang.foreign.MemorySegment _x6, java.lang.foreign.MemorySegment _x7); - static MemorySegment allocate(WritePipeAsyncTO fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$37.const$2, fi, constants$36.const$4, scope); - } - static WritePipeAsyncTO ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, java.lang.foreign.MemorySegment __x2, int __x3, int __x4, int __x5, java.lang.foreign.MemorySegment __x6, java.lang.foreign.MemorySegment __x7) -> { - try { - return (int)constants$37.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6, __x7); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long ClearPipeStallBothEnds$offset() { + return ClearPipeStallBothEnds$OFFSET; } - public static VarHandle WritePipeAsyncTO$VH() { - return constants$37.const$3; - } /** * Getter for field: - * {@snippet : - * IOReturn (*WritePipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8) * } */ - public static MemorySegment WritePipeAsyncTO$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$37.const$3.get(seg); + public static MemorySegment ClearPipeStallBothEnds(MemorySegment struct) { + return struct.get(ClearPipeStallBothEnds$LAYOUT, ClearPipeStallBothEnds$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*WritePipeAsyncTO)(void*,UInt8,void*,UInt32,UInt32,UInt32,IOAsyncCallback1,void*); + * {@snippet lang=c : + * IOReturn (*ClearPipeStallBothEnds)(void *, UInt8) * } */ - public static void WritePipeAsyncTO$set(MemorySegment seg, MemorySegment x) { - constants$37.const$3.set(seg, x); - } - public static MemorySegment WritePipeAsyncTO$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$37.const$3.get(seg.asSlice(index*sizeof())); - } - public static void WritePipeAsyncTO$set(MemorySegment seg, long index, MemorySegment x) { - constants$37.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static WritePipeAsyncTO WritePipeAsyncTO(MemorySegment segment, Arena scope) { - return WritePipeAsyncTO.ofAddress(WritePipeAsyncTO$get(segment), scope); + public static void ClearPipeStallBothEnds(MemorySegment struct, MemorySegment fieldValue) { + struct.set(ClearPipeStallBothEnds$LAYOUT, ClearPipeStallBothEnds$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*USBInterfaceGetStringIndex)(void*,UInt8*); + * {@snippet lang=c : + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8) * } */ - public interface USBInterfaceGetStringIndex { + public final static class SetPipePolicy { - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(USBInterfaceGetStringIndex fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$37.const$4, fi, constants$6.const$5, scope); + private SetPipePolicy() { + // Should not be called directly } - static USBInterfaceGetStringIndex ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_SHORT, + IOKit.C_CHAR + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle USBInterfaceGetStringIndex$VH() { - return constants$37.const$5; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*USBInterfaceGetStringIndex)(void*,UInt8*); - * } - */ - public static MemorySegment USBInterfaceGetStringIndex$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$37.const$5.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, short _x2, byte _x3) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout SetPipePolicy$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("SetPipePolicy")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*USBInterfaceGetStringIndex)(void*,UInt8*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8) * } */ - public static void USBInterfaceGetStringIndex$set(MemorySegment seg, MemorySegment x) { - constants$37.const$5.set(seg, x); - } - public static MemorySegment USBInterfaceGetStringIndex$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$37.const$5.get(seg.asSlice(index*sizeof())); - } - public static void USBInterfaceGetStringIndex$set(MemorySegment seg, long index, MemorySegment x) { - constants$37.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static USBInterfaceGetStringIndex USBInterfaceGetStringIndex(MemorySegment segment, Arena scope) { - return USBInterfaceGetStringIndex.ofAddress(USBInterfaceGetStringIndex$get(segment), scope); + public static final AddressLayout SetPipePolicy$layout() { + return SetPipePolicy$LAYOUT; } + + private static final long SetPipePolicy$OFFSET = $LAYOUT.byteOffset(groupElement("SetPipePolicy")); + /** - * {@snippet : - * IOReturn (*USBInterfaceOpenSeize)(void*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8) * } */ - public interface USBInterfaceOpenSeize { - - int apply(java.lang.foreign.MemorySegment _x0); - static MemorySegment allocate(USBInterfaceOpenSeize fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$38.const$0, fi, constants$5.const$5, scope); - } - static USBInterfaceOpenSeize ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0) -> { - try { - return (int)constants$6.const$1.invokeExact(symbol, __x0); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long SetPipePolicy$offset() { + return SetPipePolicy$OFFSET; } - public static VarHandle USBInterfaceOpenSeize$VH() { - return constants$38.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*USBInterfaceOpenSeize)(void*); + * {@snippet lang=c : + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8) * } */ - public static MemorySegment USBInterfaceOpenSeize$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$38.const$1.get(seg); + public static MemorySegment SetPipePolicy(MemorySegment struct) { + return struct.get(SetPipePolicy$LAYOUT, SetPipePolicy$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*USBInterfaceOpenSeize)(void*); + * {@snippet lang=c : + * IOReturn (*SetPipePolicy)(void *, UInt8, UInt16, UInt8) * } */ - public static void USBInterfaceOpenSeize$set(MemorySegment seg, MemorySegment x) { - constants$38.const$1.set(seg, x); - } - public static MemorySegment USBInterfaceOpenSeize$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$38.const$1.get(seg.asSlice(index*sizeof())); - } - public static void USBInterfaceOpenSeize$set(MemorySegment seg, long index, MemorySegment x) { - constants$38.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static USBInterfaceOpenSeize USBInterfaceOpenSeize(MemorySegment segment, Arena scope) { - return USBInterfaceOpenSeize.ofAddress(USBInterfaceOpenSeize$get(segment), scope); + public static void SetPipePolicy(MemorySegment struct, MemorySegment fieldValue) { + struct.set(SetPipePolicy$LAYOUT, SetPipePolicy$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*ClearPipeStallBothEnds)(void*,UInt8); + * {@snippet lang=c : + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *) * } */ - public interface ClearPipeStallBothEnds { + public final static class GetBandwidthAvailable { - int apply(java.lang.foreign.MemorySegment _x0, byte _x1); - static MemorySegment allocate(ClearPipeStallBothEnds fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$38.const$2, fi, constants$14.const$0, scope); + private GetBandwidthAvailable() { + // Should not be called directly } - static ClearPipeStallBothEnds ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1) -> { - try { - return (int)constants$14.const$2.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + /** + */ + + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - } - public static VarHandle ClearPipeStallBothEnds$VH() { - return constants$38.const$3; - } - /** - * Getter for field: - * {@snippet : - * IOReturn (*ClearPipeStallBothEnds)(void*,UInt8); - * } - */ - public static MemorySegment ClearPipeStallBothEnds$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$38.const$3.get(seg); + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } + + private static final AddressLayout GetBandwidthAvailable$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetBandwidthAvailable")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*ClearPipeStallBothEnds)(void*,UInt8); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *) * } */ - public static void ClearPipeStallBothEnds$set(MemorySegment seg, MemorySegment x) { - constants$38.const$3.set(seg, x); - } - public static MemorySegment ClearPipeStallBothEnds$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$38.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ClearPipeStallBothEnds$set(MemorySegment seg, long index, MemorySegment x) { - constants$38.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static ClearPipeStallBothEnds ClearPipeStallBothEnds(MemorySegment segment, Arena scope) { - return ClearPipeStallBothEnds.ofAddress(ClearPipeStallBothEnds$get(segment), scope); + public static final AddressLayout GetBandwidthAvailable$layout() { + return GetBandwidthAvailable$LAYOUT; } + + private static final long GetBandwidthAvailable$OFFSET = $LAYOUT.byteOffset(groupElement("GetBandwidthAvailable")); + /** - * {@snippet : - * IOReturn (*SetPipePolicy)(void*,UInt8,UInt16,UInt8); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *) * } */ - public interface SetPipePolicy { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, short _x2, byte _x3); - static MemorySegment allocate(SetPipePolicy fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$38.const$5, fi, constants$38.const$4, scope); - } - static SetPipePolicy ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, short __x2, byte __x3) -> { - try { - return (int)constants$39.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static final long GetBandwidthAvailable$offset() { + return GetBandwidthAvailable$OFFSET; } - public static VarHandle SetPipePolicy$VH() { - return constants$39.const$1; - } /** * Getter for field: - * {@snippet : - * IOReturn (*SetPipePolicy)(void*,UInt8,UInt16,UInt8); + * {@snippet lang=c : + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *) * } */ - public static MemorySegment SetPipePolicy$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$39.const$1.get(seg); + public static MemorySegment GetBandwidthAvailable(MemorySegment struct) { + return struct.get(GetBandwidthAvailable$LAYOUT, GetBandwidthAvailable$OFFSET); } + /** * Setter for field: - * {@snippet : - * IOReturn (*SetPipePolicy)(void*,UInt8,UInt16,UInt8); + * {@snippet lang=c : + * IOReturn (*GetBandwidthAvailable)(void *, UInt32 *) * } */ - public static void SetPipePolicy$set(MemorySegment seg, MemorySegment x) { - constants$39.const$1.set(seg, x); - } - public static MemorySegment SetPipePolicy$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$39.const$1.get(seg.asSlice(index*sizeof())); - } - public static void SetPipePolicy$set(MemorySegment seg, long index, MemorySegment x) { - constants$39.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static SetPipePolicy SetPipePolicy(MemorySegment segment, Arena scope) { - return SetPipePolicy.ofAddress(SetPipePolicy$get(segment), scope); + public static void GetBandwidthAvailable(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetBandwidthAvailable$LAYOUT, GetBandwidthAvailable$OFFSET, fieldValue); } + /** - * {@snippet : - * IOReturn (*GetBandwidthAvailable)(void*,UInt32*); + * {@snippet lang=c : + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *) * } */ - public interface GetBandwidthAvailable { + public final static class GetEndpointProperties { + + private GetEndpointProperties() { + // Should not be called directly + } + + /** + */ - int apply(java.lang.foreign.MemorySegment _x0, java.lang.foreign.MemorySegment _x1); - static MemorySegment allocate(GetBandwidthAvailable fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$39.const$2, fi, constants$6.const$5, scope); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of( + IOKit.C_INT, + IOKit.C_POINTER, + IOKit.C_CHAR, + IOKit.C_CHAR, + IOKit.C_CHAR, + IOKit.C_POINTER, + IOKit.C_POINTER, + IOKit.C_POINTER + ); + + /** + * The descriptor of this function pointer + */ + public static FunctionDescriptor descriptor() { + return $DESC; } - static GetBandwidthAvailable ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, java.lang.foreign.MemorySegment __x1) -> { - try { - return (int)constants$7.const$1.invokeExact(symbol, __x0, __x1); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; + + + private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); + + /** + * Invoke the upcall stub {@code funcPtr}, with given parameters + */ + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, byte _x1, byte _x2, byte _x3, MemorySegment _x4, MemorySegment _x5, MemorySegment _x6) { + try { + return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5, _x6); + } catch (Error | RuntimeException ex) { + throw ex; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } } - public static VarHandle GetBandwidthAvailable$VH() { - return constants$39.const$3; - } + private static final AddressLayout GetEndpointProperties$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("GetEndpointProperties")); + /** - * Getter for field: - * {@snippet : - * IOReturn (*GetBandwidthAvailable)(void*,UInt32*); + * Layout for field: + * {@snippet lang=c : + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *) * } */ - public static MemorySegment GetBandwidthAvailable$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$39.const$3.get(seg); + public static final AddressLayout GetEndpointProperties$layout() { + return GetEndpointProperties$LAYOUT; } + + private static final long GetEndpointProperties$OFFSET = $LAYOUT.byteOffset(groupElement("GetEndpointProperties")); + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetBandwidthAvailable)(void*,UInt32*); + * Offset for field: + * {@snippet lang=c : + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *) * } */ - public static void GetBandwidthAvailable$set(MemorySegment seg, MemorySegment x) { - constants$39.const$3.set(seg, x); - } - public static MemorySegment GetBandwidthAvailable$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$39.const$3.get(seg.asSlice(index*sizeof())); - } - public static void GetBandwidthAvailable$set(MemorySegment seg, long index, MemorySegment x) { - constants$39.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static GetBandwidthAvailable GetBandwidthAvailable(MemorySegment segment, Arena scope) { - return GetBandwidthAvailable.ofAddress(GetBandwidthAvailable$get(segment), scope); + public static final long GetEndpointProperties$offset() { + return GetEndpointProperties$OFFSET; } + /** - * {@snippet : - * IOReturn (*GetEndpointProperties)(void*,UInt8,UInt8,UInt8,UInt8*,UInt16*,UInt8*); + * Getter for field: + * {@snippet lang=c : + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *) * } */ - public interface GetEndpointProperties { - - int apply(java.lang.foreign.MemorySegment _x0, byte _x1, byte _x2, byte _x3, java.lang.foreign.MemorySegment _x4, java.lang.foreign.MemorySegment _x5, java.lang.foreign.MemorySegment _x6); - static MemorySegment allocate(GetEndpointProperties fi, Arena scope) { - return RuntimeHelper.upcallStub(constants$39.const$5, fi, constants$39.const$4, scope); - } - static GetEndpointProperties ofAddress(MemorySegment addr, Arena arena) { - MemorySegment symbol = addr.reinterpret(arena, null); - return (java.lang.foreign.MemorySegment __x0, byte __x1, byte __x2, byte __x3, java.lang.foreign.MemorySegment __x4, java.lang.foreign.MemorySegment __x5, java.lang.foreign.MemorySegment __x6) -> { - try { - return (int)constants$40.const$0.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5, __x6); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }; - } + public static MemorySegment GetEndpointProperties(MemorySegment struct) { + return struct.get(GetEndpointProperties$LAYOUT, GetEndpointProperties$OFFSET); } - public static VarHandle GetEndpointProperties$VH() { - return constants$40.const$1; - } /** - * Getter for field: - * {@snippet : - * IOReturn (*GetEndpointProperties)(void*,UInt8,UInt8,UInt8,UInt8*,UInt16*,UInt8*); + * Setter for field: + * {@snippet lang=c : + * IOReturn (*GetEndpointProperties)(void *, UInt8, UInt8, UInt8, UInt8 *, UInt16 *, UInt8 *) * } */ - public static MemorySegment GetEndpointProperties$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$40.const$1.get(seg); + public static void GetEndpointProperties(MemorySegment struct, MemorySegment fieldValue) { + struct.set(GetEndpointProperties$LAYOUT, GetEndpointProperties$OFFSET, fieldValue); } + /** - * Setter for field: - * {@snippet : - * IOReturn (*GetEndpointProperties)(void*,UInt8,UInt8,UInt8,UInt8*,UInt16*,UInt8*); - * } + * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. + * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} */ - public static void GetEndpointProperties$set(MemorySegment seg, MemorySegment x) { - constants$40.const$1.set(seg, x); + public static MemorySegment asSlice(MemorySegment array, long index) { + return array.asSlice(layout().byteSize() * index); } - public static MemorySegment GetEndpointProperties$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$40.const$1.get(seg.asSlice(index*sizeof())); + + /** + * The size (in bytes) of this struct + */ + public static long sizeof() { return layout().byteSize(); } + + /** + * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} + */ + public static MemorySegment allocate(SegmentAllocator allocator) { + return allocator.allocate(layout()); } - public static void GetEndpointProperties$set(MemorySegment seg, long index, MemorySegment x) { - constants$40.const$1.set(seg.asSlice(index*sizeof()), x); + + /** + * Allocate an array of size {@code elementCount} using {@code allocator}. + * The returned segment has size {@code elementCount * layout().byteSize()}. + */ + public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { + return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); } - public static GetEndpointProperties GetEndpointProperties(MemorySegment segment, Arena scope) { - return GetEndpointProperties.ofAddress(GetEndpointProperties$get(segment), scope); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { + return reinterpret(addr, 1, arena, cleanup); } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); + + /** + * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). + * The returned segment has size {@code elementCount * layout().byteSize()} + */ + public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { + return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/RuntimeHelper.java deleted file mode 100644 index 6b52deb2..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/RuntimeHelper.java +++ /dev/null @@ -1,228 +0,0 @@ -package net.codecrete.usb.macos.gen.iokit; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { -// System.loadLibrary("IOKit.framework"); -// SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SymbolLookup loaderLookup = SymbolLookup.libraryLookup("IOKit.framework/IOKit", Arena.global()); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$0.java deleted file mode 100644 index 0c05b256..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$0.java +++ /dev/null @@ -1,31 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_BYTE.withName("bmRequestType"), - JAVA_BYTE.withName("bRequest"), - JAVA_SHORT.withName("wValue"), - JAVA_SHORT.withName("wIndex"), - JAVA_SHORT.withName("wLength"), - RuntimeHelper.POINTER.withName("pData"), - JAVA_INT.withName("wLenDone"), - MemoryLayout.paddingLayout(4) - ).withName(""); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("bmRequestType")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("bRequest")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wValue")); - static final VarHandle const$4 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wIndex")); - static final VarHandle const$5 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wLength")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$1.java deleted file mode 100644 index 7f197c64..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$1.java +++ /dev/null @@ -1,27 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_SHORT; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final VarHandle const$0 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("pData")); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("wLenDone")); - static final StructLayout const$2 = MemoryLayout.structLayout( - JAVA_SHORT.withName("bInterfaceClass"), - JAVA_SHORT.withName("bInterfaceSubClass"), - JAVA_SHORT.withName("bInterfaceProtocol"), - JAVA_SHORT.withName("bAlternateSetting") - ).withName(""); - static final VarHandle const$3 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("bInterfaceClass")); - static final VarHandle const$4 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("bInterfaceSubClass")); - static final VarHandle const$5 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("bInterfaceProtocol")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$10.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$10.java deleted file mode 100644 index 45874636..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$10.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$10 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$10() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceProtocol.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceProtocol")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceVendor.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceVendor")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceProduct.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceProduct")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$11.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$11.java deleted file mode 100644 index 9e28e1bf..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$11.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$11 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$11() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceReleaseNumber.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceReleaseNumber")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceAddress.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceAddress")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceBusPowerAvailable.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceBusPowerAvailable")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$12.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$12.java deleted file mode 100644 index 13c8d1fd..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$12.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$12 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$12() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceSpeed.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceSpeed")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetNumberOfConfigurations.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetNumberOfConfigurations")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetLocationID.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetLocationID")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$13.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$13.java deleted file mode 100644 index 39624ca6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$13.java +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$13 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$13() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetConfigurationDescriptorPtr.class, "apply", constants$13.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$13.const$0 - ); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetConfigurationDescriptorPtr")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetConfiguration.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetConfiguration")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$14.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$14.java deleted file mode 100644 index f392ab2d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$14.java +++ /dev/null @@ -1,33 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$14 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$14() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.SetConfiguration.class, "apply", constants$14.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$14.const$0 - ); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("SetConfiguration")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetBusFrameNumber.class, "apply", constants$14.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$15.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$15.java deleted file mode 100644 index 79a39ca9..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$15.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$15 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$15() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$14.const$4 - ); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetBusFrameNumber")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.ResetDevice.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("ResetDevice")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.DeviceRequest.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("DeviceRequest")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$16.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$16.java deleted file mode 100644 index 4aaba200..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$16.java +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$16 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$16() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.DeviceRequestAsync.class, "apply", constants$16.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$16.const$0 - ); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("DeviceRequestAsync")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.CreateInterfaceIterator.class, "apply", constants$14.const$4); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("CreateInterfaceIterator")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$17.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$17.java deleted file mode 100644 index 18fbc0e1..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$17.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$17 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$17() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceOpenSeize.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceOpenSeize")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.DeviceRequestTO.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("DeviceRequestTO")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.DeviceRequestAsyncTO.class, "apply", constants$16.const$0); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("DeviceRequestAsyncTO")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$18.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$18.java deleted file mode 100644 index c5cc1d28..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$18.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$18 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$18() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceSuspend.class, "apply", constants$14.const$0); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceSuspend")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceAbortPipeZero.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceAbortPipeZero")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBGetManufacturerStringIndex.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBGetManufacturerStringIndex")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$19.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$19.java deleted file mode 100644 index a1df6f77..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$19.java +++ /dev/null @@ -1,26 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$19 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$19() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBGetProductStringIndex.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBGetProductStringIndex")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBGetSerialNumberStringIndex.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBGetSerialNumberStringIndex")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceReEnumerate.class, "apply", constants$19.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$2.java deleted file mode 100644 index 0e4c4512..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$2.java +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final VarHandle const$0 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("bAlternateSetting")); - static final VarHandle const$1 = RuntimeHelper.POINTER.varHandle(); - static final MemorySegment const$2 = RuntimeHelper.lookupGlobalVariable("kCFRunLoopDefaultMode", RuntimeHelper.POINTER); - static final VarHandle const$3 = JAVA_INT.varHandle(); - static final MemorySegment const$4 = RuntimeHelper.lookupGlobalVariable("kIOMasterPortDefault", JAVA_INT); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "IONotificationPortCreate", - constants$2.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$20.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$20.java deleted file mode 100644 index a7e481c4..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$20.java +++ /dev/null @@ -1,73 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$20 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$20() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$19.const$4 - ); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceReEnumerate")); - static final StructLayout const$2 = MemoryLayout.structLayout( - RuntimeHelper.POINTER.withName("_reserved"), - RuntimeHelper.POINTER.withName("QueryInterface"), - RuntimeHelper.POINTER.withName("AddRef"), - RuntimeHelper.POINTER.withName("Release"), - RuntimeHelper.POINTER.withName("CreateInterfaceAsyncEventSource"), - RuntimeHelper.POINTER.withName("GetInterfaceAsyncEventSource"), - RuntimeHelper.POINTER.withName("CreateInterfaceAsyncPort"), - RuntimeHelper.POINTER.withName("GetInterfaceAsyncPort"), - RuntimeHelper.POINTER.withName("USBInterfaceOpen"), - RuntimeHelper.POINTER.withName("USBInterfaceClose"), - RuntimeHelper.POINTER.withName("GetInterfaceClass"), - RuntimeHelper.POINTER.withName("GetInterfaceSubClass"), - RuntimeHelper.POINTER.withName("GetInterfaceProtocol"), - RuntimeHelper.POINTER.withName("GetDeviceVendor"), - RuntimeHelper.POINTER.withName("GetDeviceProduct"), - RuntimeHelper.POINTER.withName("GetDeviceReleaseNumber"), - RuntimeHelper.POINTER.withName("GetConfigurationValue"), - RuntimeHelper.POINTER.withName("GetInterfaceNumber"), - RuntimeHelper.POINTER.withName("GetAlternateSetting"), - RuntimeHelper.POINTER.withName("GetNumEndpoints"), - RuntimeHelper.POINTER.withName("GetLocationID"), - RuntimeHelper.POINTER.withName("GetDevice"), - RuntimeHelper.POINTER.withName("SetAlternateInterface"), - RuntimeHelper.POINTER.withName("GetBusFrameNumber"), - RuntimeHelper.POINTER.withName("ControlRequest"), - RuntimeHelper.POINTER.withName("ControlRequestAsync"), - RuntimeHelper.POINTER.withName("GetPipeProperties"), - RuntimeHelper.POINTER.withName("GetPipeStatus"), - RuntimeHelper.POINTER.withName("AbortPipe"), - RuntimeHelper.POINTER.withName("ResetPipe"), - RuntimeHelper.POINTER.withName("ClearPipeStall"), - RuntimeHelper.POINTER.withName("ReadPipe"), - RuntimeHelper.POINTER.withName("WritePipe"), - RuntimeHelper.POINTER.withName("ReadPipeAsync"), - RuntimeHelper.POINTER.withName("WritePipeAsync"), - RuntimeHelper.POINTER.withName("ReadIsochPipeAsync"), - RuntimeHelper.POINTER.withName("WriteIsochPipeAsync"), - RuntimeHelper.POINTER.withName("ControlRequestTO"), - RuntimeHelper.POINTER.withName("ControlRequestAsyncTO"), - RuntimeHelper.POINTER.withName("ReadPipeTO"), - RuntimeHelper.POINTER.withName("WritePipeTO"), - RuntimeHelper.POINTER.withName("ReadPipeAsyncTO"), - RuntimeHelper.POINTER.withName("WritePipeAsyncTO"), - RuntimeHelper.POINTER.withName("USBInterfaceGetStringIndex"), - RuntimeHelper.POINTER.withName("USBInterfaceOpenSeize"), - RuntimeHelper.POINTER.withName("ClearPipeStallBothEnds"), - RuntimeHelper.POINTER.withName("SetPipePolicy"), - RuntimeHelper.POINTER.withName("GetBandwidthAvailable"), - RuntimeHelper.POINTER.withName("GetEndpointProperties") - ).withName("IOUSBInterfaceStruct190"); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("_reserved")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.QueryInterface.class, "apply", constants$5.const$1); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("QueryInterface")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$21.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$21.java deleted file mode 100644 index 11a65d3b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$21.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$21 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$21() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.AddRef.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("AddRef")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.Release.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("Release")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.CreateInterfaceAsyncEventSource.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("CreateInterfaceAsyncEventSource")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$22.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$22.java deleted file mode 100644 index c7b34333..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$22.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$22 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$22() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceAsyncEventSource.class, "apply", constants$3.const$0); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceAsyncEventSource")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.CreateInterfaceAsyncPort.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("CreateInterfaceAsyncPort")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceAsyncPort.class, "apply", constants$5.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceAsyncPort")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$23.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$23.java deleted file mode 100644 index 51f5726d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$23.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$23 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$23() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.USBInterfaceOpen.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("USBInterfaceOpen")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.USBInterfaceClose.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("USBInterfaceClose")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceClass.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceClass")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$24.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$24.java deleted file mode 100644 index 5f698e5c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$24.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$24 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$24() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceSubClass.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceSubClass")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceProtocol.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceProtocol")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetDeviceVendor.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceVendor")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$25.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$25.java deleted file mode 100644 index ac0ee5fd..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$25.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$25 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$25() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetDeviceProduct.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceProduct")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetDeviceReleaseNumber.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceReleaseNumber")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetConfigurationValue.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetConfigurationValue")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$26.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$26.java deleted file mode 100644 index 63ae0b5c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$26.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$26 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$26() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetInterfaceNumber.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetInterfaceNumber")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetAlternateSetting.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetAlternateSetting")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetNumEndpoints.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetNumEndpoints")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$27.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$27.java deleted file mode 100644 index 3623d41b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$27.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$27 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$27() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetLocationID.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetLocationID")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetDevice.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetDevice")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.SetAlternateInterface.class, "apply", constants$14.const$0); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("SetAlternateInterface")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$28.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$28.java deleted file mode 100644 index b34eb80a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$28.java +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$28 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$28() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetBusFrameNumber.class, "apply", constants$14.const$4); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetBusFrameNumber")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ControlRequest.class, "apply", constants$13.const$0); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ControlRequest")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ControlRequestAsync.class, "apply", constants$28.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$29.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$29.java deleted file mode 100644 index a5466229..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$29.java +++ /dev/null @@ -1,36 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$29 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$29() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$28.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ControlRequestAsync")); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetPipeProperties.class, "apply", constants$29.const$2); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - constants$29.const$2 - ); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetPipeProperties")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$3.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$3.java deleted file mode 100644 index 320ddc7f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$3.java +++ /dev/null @@ -1,45 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$3 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$3() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "IONotificationPortGetRunLoopSource", - constants$3.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - JAVA_INT - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "IOObjectRelease", - constants$3.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "IOIteratorNext", - constants$3.const$2 - ); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "IOServiceAddMatchingNotification", - constants$3.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$30.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$30.java deleted file mode 100644 index ab553ef3..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$30.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$30 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$30() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetPipeStatus.class, "apply", constants$14.const$0); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetPipeStatus")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.AbortPipe.class, "apply", constants$14.const$0); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("AbortPipe")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ResetPipe.class, "apply", constants$14.const$0); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ResetPipe")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$31.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$31.java deleted file mode 100644 index ea1c0dbc..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$31.java +++ /dev/null @@ -1,31 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$31 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$31() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ClearPipeStall.class, "apply", constants$14.const$0); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ClearPipeStall")); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ReadPipe.class, "apply", constants$31.const$2); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - constants$31.const$2 - ); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ReadPipe")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$32.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$32.java deleted file mode 100644 index ee057f97..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$32.java +++ /dev/null @@ -1,38 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$32 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$32() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.WritePipe.class, "apply", constants$32.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$32.const$0 - ); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("WritePipe")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ReadPipeAsync.class, "apply", constants$32.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$33.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$33.java deleted file mode 100644 index ec150123..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$33.java +++ /dev/null @@ -1,34 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$33 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$33() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$32.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ReadPipeAsync")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.WritePipeAsync.class, "apply", constants$32.const$4); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("WritePipeAsync")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_LONG, - JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ReadIsochPipeAsync.class, "apply", constants$33.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$34.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$34.java deleted file mode 100644 index 0dd3c4c6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$34.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$34 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$34() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$33.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ReadIsochPipeAsync")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.WriteIsochPipeAsync.class, "apply", constants$33.const$4); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("WriteIsochPipeAsync")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ControlRequestTO.class, "apply", constants$13.const$0); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ControlRequestTO")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$35.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$35.java deleted file mode 100644 index 315b2f75..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$35.java +++ /dev/null @@ -1,33 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$35 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$35() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ControlRequestAsyncTO.class, "apply", constants$28.const$4); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ControlRequestAsyncTO")); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - JAVA_INT, - JAVA_INT - ); - static final MethodHandle const$3 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ReadPipeTO.class, "apply", constants$35.const$2); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - constants$35.const$2 - ); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ReadPipeTO")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$36.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$36.java deleted file mode 100644 index bd7bf064..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$36.java +++ /dev/null @@ -1,42 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$36 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$36() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_INT, - JAVA_INT, - JAVA_INT - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.WritePipeTO.class, "apply", constants$36.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$36.const$0 - ); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("WritePipeTO")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - RuntimeHelper.POINTER, - JAVA_INT, - JAVA_INT, - JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ReadPipeAsyncTO.class, "apply", constants$36.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$37.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$37.java deleted file mode 100644 index 0d52f7d0..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$37.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$37 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$37() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$36.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ReadPipeAsyncTO")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.WritePipeAsyncTO.class, "apply", constants$36.const$4); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("WritePipeAsyncTO")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.USBInterfaceGetStringIndex.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("USBInterfaceGetStringIndex")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$38.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$38.java deleted file mode 100644 index ce319313..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$38.java +++ /dev/null @@ -1,28 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$38 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$38() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.USBInterfaceOpenSeize.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("USBInterfaceOpenSeize")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.ClearPipeStallBothEnds.class, "apply", constants$14.const$0); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("ClearPipeStallBothEnds")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - JAVA_SHORT, - JAVA_BYTE - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.SetPipePolicy.class, "apply", constants$38.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$39.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$39.java deleted file mode 100644 index 0aaa0f85..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$39.java +++ /dev/null @@ -1,34 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$39 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$39() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$38.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("SetPipePolicy")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetBandwidthAvailable.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetBandwidthAvailable")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - JAVA_BYTE, - JAVA_BYTE, - JAVA_BYTE, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOUSBInterfaceStruct190.GetEndpointProperties.class, "apply", constants$39.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$4.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$4.java deleted file mode 100644 index 2118e4f6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$4.java +++ /dev/null @@ -1,79 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$4 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$4() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "IORegistryEntryGetRegistryEntryID", - constants$4.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(RuntimeHelper.POINTER, - JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "IORegistryEntryCreateCFProperty", - constants$4.const$2 - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "IOServiceMatching", - constants$3.const$0 - ); - static final StructLayout const$5 = MemoryLayout.structLayout( - RuntimeHelper.POINTER.withName("_reserved"), - RuntimeHelper.POINTER.withName("QueryInterface"), - RuntimeHelper.POINTER.withName("AddRef"), - RuntimeHelper.POINTER.withName("Release"), - RuntimeHelper.POINTER.withName("CreateDeviceAsyncEventSource"), - RuntimeHelper.POINTER.withName("GetDeviceAsyncEventSource"), - RuntimeHelper.POINTER.withName("CreateDeviceAsyncPort"), - RuntimeHelper.POINTER.withName("GetDeviceAsyncPort"), - RuntimeHelper.POINTER.withName("USBDeviceOpen"), - RuntimeHelper.POINTER.withName("USBDeviceClose"), - RuntimeHelper.POINTER.withName("GetDeviceClass"), - RuntimeHelper.POINTER.withName("GetDeviceSubClass"), - RuntimeHelper.POINTER.withName("GetDeviceProtocol"), - RuntimeHelper.POINTER.withName("GetDeviceVendor"), - RuntimeHelper.POINTER.withName("GetDeviceProduct"), - RuntimeHelper.POINTER.withName("GetDeviceReleaseNumber"), - RuntimeHelper.POINTER.withName("GetDeviceAddress"), - RuntimeHelper.POINTER.withName("GetDeviceBusPowerAvailable"), - RuntimeHelper.POINTER.withName("GetDeviceSpeed"), - RuntimeHelper.POINTER.withName("GetNumberOfConfigurations"), - RuntimeHelper.POINTER.withName("GetLocationID"), - RuntimeHelper.POINTER.withName("GetConfigurationDescriptorPtr"), - RuntimeHelper.POINTER.withName("GetConfiguration"), - RuntimeHelper.POINTER.withName("SetConfiguration"), - RuntimeHelper.POINTER.withName("GetBusFrameNumber"), - RuntimeHelper.POINTER.withName("ResetDevice"), - RuntimeHelper.POINTER.withName("DeviceRequest"), - RuntimeHelper.POINTER.withName("DeviceRequestAsync"), - RuntimeHelper.POINTER.withName("CreateInterfaceIterator"), - RuntimeHelper.POINTER.withName("USBDeviceOpenSeize"), - RuntimeHelper.POINTER.withName("DeviceRequestTO"), - RuntimeHelper.POINTER.withName("DeviceRequestAsyncTO"), - RuntimeHelper.POINTER.withName("USBDeviceSuspend"), - RuntimeHelper.POINTER.withName("USBDeviceAbortPipeZero"), - RuntimeHelper.POINTER.withName("USBGetManufacturerStringIndex"), - RuntimeHelper.POINTER.withName("USBGetProductStringIndex"), - RuntimeHelper.POINTER.withName("USBGetSerialNumberStringIndex"), - RuntimeHelper.POINTER.withName("USBDeviceReEnumerate") - ).withName("IOUSBDeviceStruct187"); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$40.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$40.java deleted file mode 100644 index e5407f3a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$40.java +++ /dev/null @@ -1,36 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_SHORT; -final class constants$40 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$40() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$39.const$4 - ); - static final VarHandle const$1 = constants$20.const$2.varHandle(MemoryLayout.PathElement.groupElement("GetEndpointProperties")); - static final StructLayout const$2 = MemoryLayout.structLayout( - RuntimeHelper.POINTER.withName("_reserved"), - RuntimeHelper.POINTER.withName("QueryInterface"), - RuntimeHelper.POINTER.withName("AddRef"), - RuntimeHelper.POINTER.withName("Release"), - JAVA_SHORT.withName("version"), - JAVA_SHORT.withName("revision"), - MemoryLayout.paddingLayout(4), - RuntimeHelper.POINTER.withName("Probe"), - RuntimeHelper.POINTER.withName("Start"), - RuntimeHelper.POINTER.withName("Stop") - ).withName("IOCFPlugInInterfaceStruct"); - static final VarHandle const$3 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("_reserved")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.QueryInterface.class, "apply", constants$5.const$1); - static final VarHandle const$5 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("QueryInterface")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$41.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$41.java deleted file mode 100644 index 8b77227c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$41.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$41 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$41() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.AddRef.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("AddRef")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.Release.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("Release")); - static final VarHandle const$4 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("version")); - static final VarHandle const$5 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("revision")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$42.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$42.java deleted file mode 100644 index 4ed42f8d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$42.java +++ /dev/null @@ -1,34 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$42 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$42() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.Probe.class, "apply", constants$42.const$0); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - constants$42.const$0 - ); - static final VarHandle const$3 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("Probe")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$5 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.Start.class, "apply", constants$42.const$4); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$43.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$43.java deleted file mode 100644 index 8ad9ceff..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$43.java +++ /dev/null @@ -1,34 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$43 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$43() {} - static final MethodHandle const$0 = RuntimeHelper.downcallHandle( - constants$42.const$4 - ); - static final VarHandle const$1 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("Start")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOCFPlugInInterfaceStruct.Stop.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$40.const$2.varHandle(MemoryLayout.PathElement.groupElement("Stop")); - static final FunctionDescriptor const$4 = FunctionDescriptor.of(JAVA_INT, - JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$5 = RuntimeHelper.downcallHandle( - "IOCreatePlugInInterfaceForService", - constants$43.const$4 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$44.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$44.java deleted file mode 100644 index c074540f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$44.java +++ /dev/null @@ -1,15 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemorySegment; -final class constants$44 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$44() {} - static final MemorySegment const$0 = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("IOServiceFirstMatch"); - static final MemorySegment const$1 = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("IOServiceTerminate"); - static final MemorySegment const$2 = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("IOUSBDevice"); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$5.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$5.java deleted file mode 100644 index b604c1c6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$5.java +++ /dev/null @@ -1,49 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$5 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$5() {} - static final VarHandle const$0 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("_reserved")); - static final FunctionDescriptor const$1 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - MemoryLayout.structLayout( - JAVA_BYTE.withName("byte0"), - JAVA_BYTE.withName("byte1"), - JAVA_BYTE.withName("byte2"), - JAVA_BYTE.withName("byte3"), - JAVA_BYTE.withName("byte4"), - JAVA_BYTE.withName("byte5"), - JAVA_BYTE.withName("byte6"), - JAVA_BYTE.withName("byte7"), - JAVA_BYTE.withName("byte8"), - JAVA_BYTE.withName("byte9"), - JAVA_BYTE.withName("byte10"), - JAVA_BYTE.withName("byte11"), - JAVA_BYTE.withName("byte12"), - JAVA_BYTE.withName("byte13"), - JAVA_BYTE.withName("byte14"), - JAVA_BYTE.withName("byte15") - ).withName(""), - RuntimeHelper.POINTER - ); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.QueryInterface.class, "apply", constants$5.const$1); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - constants$5.const$1 - ); - static final VarHandle const$4 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("QueryInterface")); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$6.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$6.java deleted file mode 100644 index eef323d4..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$6.java +++ /dev/null @@ -1,28 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$6 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$6() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.AddRef.class, "apply", constants$5.const$5); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - constants$5.const$5 - ); - static final VarHandle const$2 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("AddRef")); - static final MethodHandle const$3 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.Release.class, "apply", constants$5.const$5); - static final VarHandle const$4 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("Release")); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$7.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$7.java deleted file mode 100644 index 5ac5bfcb..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$7.java +++ /dev/null @@ -1,24 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$7 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$7() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.CreateDeviceAsyncEventSource.class, "apply", constants$6.const$5); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - constants$6.const$5 - ); - static final VarHandle const$2 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("CreateDeviceAsyncEventSource")); - static final MethodHandle const$3 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceAsyncEventSource.class, "apply", constants$3.const$0); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - constants$3.const$0 - ); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceAsyncEventSource")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$8.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$8.java deleted file mode 100644 index 9793b458..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$8.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$8 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$8() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.CreateDeviceAsyncPort.class, "apply", constants$6.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("CreateDeviceAsyncPort")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceAsyncPort.class, "apply", constants$5.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceAsyncPort")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceOpen.class, "apply", constants$5.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceOpen")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$9.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$9.java deleted file mode 100644 index fccbf566..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/iokit/constants$9.java +++ /dev/null @@ -1,20 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.iokit; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; -final class constants$9 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$9() {} - static final MethodHandle const$0 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.USBDeviceClose.class, "apply", constants$5.const$5); - static final VarHandle const$1 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("USBDeviceClose")); - static final MethodHandle const$2 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceClass.class, "apply", constants$6.const$5); - static final VarHandle const$3 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceClass")); - static final MethodHandle const$4 = RuntimeHelper.upcallHandle(IOUSBDeviceStruct187.GetDeviceSubClass.class, "apply", constants$6.const$5); - static final VarHandle const$5 = constants$4.const$5.varHandle(MemoryLayout.PathElement.groupElement("GetDeviceSubClass")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/RuntimeHelper.java deleted file mode 100644 index 1f0d63c5..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.macos.gen.mach; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/constants$0.java deleted file mode 100644 index 433609ea..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/constants$0.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.macos.gen.mach; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER, - JAVA_INT - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "mach_error_string", - constants$0.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach$shared.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach$shared.java new file mode 100644 index 00000000..afa05d01 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach$shared.java @@ -0,0 +1,63 @@ +// Generated by jextract + +package net.codecrete.usb.macos.gen.mach; + +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class mach$shared { + + mach$shared() { + // Should not be called directly + } + + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) Linker.nativeLinker().canonicalLayouts().get("bool"); + public static final ValueLayout.OfByte C_CHAR =(ValueLayout.OfByte)Linker.nativeLinker().canonicalLayouts().get("char"); + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) Linker.nativeLinker().canonicalLayouts().get("short"); + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) Linker.nativeLinker().canonicalLayouts().get("int"); + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long long"); + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) Linker.nativeLinker().canonicalLayouts().get("float"); + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) Linker.nativeLinker().canonicalLayouts().get("double"); + public static final AddressLayout C_POINTER = ((AddressLayout) Linker.nativeLinker().canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, C_CHAR)); + public static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) Linker.nativeLinker().canonicalLayouts().get("long"); + + static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + static void traceDowncall(String name, Object... args) { + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); + } + + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = g.memberLayouts().stream() + .map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? + MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } +} + diff --git a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach.java b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach.java index b53bd86f..80f92c11 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/macos/gen/mach/mach.java @@ -2,37 +2,86 @@ package net.codecrete.usb.macos.gen.mach; -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; +import java.lang.foreign.*; +import java.nio.ByteOrder; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; import static java.lang.foreign.ValueLayout.*; -public class mach { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfLong C_LONG = JAVA_LONG; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle mach_error_string$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"mach_error_string"); +import static java.lang.foreign.MemoryLayout.PathElement.*; + +public class mach extends mach$shared { + + mach() { + // Should not be called directly + } + + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + + static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + + + private static class mach_error_string { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + mach.C_POINTER, + mach.C_INT + ); + + public static final MemorySegment ADDR = SYMBOL_LOOKUP.findOrThrow("mach_error_string"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * char *mach_error_string(mach_error_t error_value) + * } + */ + public static FunctionDescriptor mach_error_string$descriptor() { + return mach_error_string.DESC; } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * char *mach_error_string(mach_error_t error_value) + * } + */ + public static MethodHandle mach_error_string$handle() { + return mach_error_string.HANDLE; + } + /** - * {@snippet : - * char* mach_error_string(mach_error_t error_value); + * Address for: + * {@snippet lang=c : + * char *mach_error_string(mach_error_t error_value) + * } + */ + public static MemorySegment mach_error_string$address() { + return mach_error_string.ADDR; + } + + /** + * {@snippet lang=c : + * char *mach_error_string(mach_error_t error_value) * } */ public static MemorySegment mach_error_string(int error_value) { - var mh$ = mach_error_string$MH(); + var mh$ = mach_error_string.HANDLE; try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(error_value); + if (TRACE_DOWNCALLS) { + traceDowncall("mach_error_string", error_value); + } + return (MemorySegment)mh$.invokeExact(error_value); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } } - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/ConfigurationDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/ConfigurationDescriptor.java index 611e76f0..5f651820 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/ConfigurationDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/ConfigurationDescriptor.java @@ -9,9 +9,7 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED; @@ -19,7 +17,7 @@ /** * USB configuration descriptor */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class ConfigurationDescriptor { private final MemorySegment descriptor; @@ -29,31 +27,31 @@ public ConfigurationDescriptor(MemorySegment descriptor) { } public int descriptorType() { - return 0xff & (byte) bDescriptorType$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bDescriptorType$OFFSET); } public int totalLength() { - return 0xffff & (short) wTotalLength$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, wTotalLength$OFFSET); } public int numInterfaces() { - return 0xff & (byte) bNumInterfaces$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bNumInterfaces$OFFSET); } public int configurationValue() { - return 0xff & (byte) bConfigurationValue$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bConfigurationValue$OFFSET); } public int iConfiguration() { - return 0xff & (byte) iConfiguration$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, iConfiguration$OFFSET); } public int attributes() { - return 0xff & (byte) bmAttributes$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bmAttributes$OFFSET); } public int maxPower() { - return 0xff & (byte) bMaxPower$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bMaxPower$OFFSET); } @@ -78,13 +76,13 @@ public int maxPower() { JAVA_BYTE.withName("bMaxPower") ); - private static final VarHandle bDescriptorType$VH = LAYOUT.varHandle(groupElement("bDescriptorType")); - private static final VarHandle wTotalLength$VH = LAYOUT.varHandle(groupElement("wTotalLength")); - private static final VarHandle bNumInterfaces$VH = LAYOUT.varHandle(groupElement("bNumInterfaces")); - private static final VarHandle bConfigurationValue$VH = LAYOUT.varHandle(groupElement("bConfigurationValue")); - private static final VarHandle iConfiguration$VH = LAYOUT.varHandle(groupElement("iConfiguration")); - private static final VarHandle bmAttributes$VH = LAYOUT.varHandle(groupElement("bmAttributes")); - private static final VarHandle bMaxPower$VH = LAYOUT.varHandle(groupElement("bMaxPower")); + private static final long bDescriptorType$OFFSET = 1; + private static final long wTotalLength$OFFSET = 2; + private static final long bNumInterfaces$OFFSET = 4; + private static final long bConfigurationValue$OFFSET = 5; + private static final long iConfiguration$OFFSET = 6; + private static final long bmAttributes$OFFSET = 7; + private static final long bMaxPower$OFFSET = 8; static { assert LAYOUT.byteSize() == 9; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/DeviceDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/DeviceDescriptor.java index 686e2a14..d122711d 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/DeviceDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/DeviceDescriptor.java @@ -9,9 +9,7 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED; @@ -19,7 +17,7 @@ /** * USB device descriptor */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class DeviceDescriptor { private final MemorySegment descriptor; @@ -29,43 +27,43 @@ public DeviceDescriptor(MemorySegment descriptor) { } public int usbVersion() { - return 0xffff & (short) bcdUSB$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, bcdUSB$OFFSET); } public int deviceClass() { - return 0xff & (byte) bDeviceClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bDeviceClass$OFFSET); } public int deviceSubClass() { - return 0xff & (byte) bDeviceSubClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bDeviceSubClass$OFFSET); } public int deviceProtocol() { - return 0xff & (byte) bDeviceProtocol$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bDeviceProtocol$OFFSET); } public int vendorID() { - return 0xffff & (short) idVendor$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, idVendor$OFFSET); } public int productID() { - return 0xffff & (short) idProduct$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, idProduct$OFFSET); } public int deviceVersion() { - return 0xffff & (short) bcdDevice$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, bcdDevice$OFFSET); } public int iManufacturer() { - return 0xffff & (short) iManufacturer$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, iManufacturer$OFFSET); } public int iProduct() { - return 0xffff & (short) iProduct$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, iProduct$OFFSET); } public int iSerialNumber() { - return 0xffff & (short) iSerialNumber$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, iSerialNumber$OFFSET); } // struct USBDeviceDescriptor { @@ -101,16 +99,16 @@ public int iSerialNumber() { JAVA_BYTE.withName("bNumConfigurations") ); - private static final VarHandle bcdUSB$VH = LAYOUT.varHandle(groupElement("bcdUSB")); - private static final VarHandle bDeviceClass$VH = LAYOUT.varHandle(groupElement("bDeviceClass")); - private static final VarHandle bDeviceSubClass$VH = LAYOUT.varHandle(groupElement("bDeviceSubClass")); - private static final VarHandle bDeviceProtocol$VH = LAYOUT.varHandle(groupElement("bDeviceProtocol")); - private static final VarHandle idVendor$VH = LAYOUT.varHandle(groupElement("idVendor")); - private static final VarHandle idProduct$VH = LAYOUT.varHandle(groupElement("idProduct")); - private static final VarHandle bcdDevice$VH = LAYOUT.varHandle(groupElement("bcdDevice")); - private static final VarHandle iManufacturer$VH = LAYOUT.varHandle(groupElement("iManufacturer")); - private static final VarHandle iProduct$VH = LAYOUT.varHandle(groupElement("iProduct")); - private static final VarHandle iSerialNumber$VH = LAYOUT.varHandle(groupElement("iSerialNumber")); + private static final long bcdUSB$OFFSET = 2; + private static final long bDeviceClass$OFFSET = 4; + private static final long bDeviceSubClass$OFFSET = 5; + private static final long bDeviceProtocol$OFFSET = 6; + private static final long idVendor$OFFSET = 8; + private static final long idProduct$OFFSET = 10; + private static final long bcdDevice$OFFSET = 12; + private static final long iManufacturer$OFFSET = 14; + private static final long iProduct$OFFSET = 15; + private static final long iSerialNumber$OFFSET = 16; static { diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/EndpointDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/EndpointDescriptor.java index a6d5516c..c45c3179 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/EndpointDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/EndpointDescriptor.java @@ -9,9 +9,7 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED; @@ -19,7 +17,7 @@ /** * USB endpoint descriptor */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class EndpointDescriptor { private final MemorySegment descriptor; @@ -33,19 +31,19 @@ public EndpointDescriptor(MemorySegment segment, long offset) { } public int endpointAddress() { - return 0xff & (byte) bEndpointAddress$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bEndpointAddress$OFFSET); } public int attributes() { - return 0xff & (byte) bmAttributes$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bmAttributes$OFFSET); } public int maxPacketSize() { - return 0xffff & (short) wMaxPacketSize$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT_UNALIGNED, wMaxPacketSize$OFFSET); } public int interval() { - return 0xff & (byte) bInterval$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterval$OFFSET); } // struct USBEndpointDescriptor { @@ -65,10 +63,10 @@ public int interval() { JAVA_BYTE.withName("bInterval") ); - private static final VarHandle bEndpointAddress$VH = LAYOUT.varHandle(groupElement("bEndpointAddress")); - private static final VarHandle bmAttributes$VH = LAYOUT.varHandle(groupElement("bmAttributes")); - private static final VarHandle wMaxPacketSize$VH = LAYOUT.varHandle(groupElement("wMaxPacketSize")); - private static final VarHandle bInterval$VH = LAYOUT.varHandle(groupElement("bInterval")); + private static final long bEndpointAddress$OFFSET = 2; + private static final long bmAttributes$OFFSET = 3; + private static final long wMaxPacketSize$OFFSET = 4; + private static final long bInterval$OFFSET = 6; static { assert LAYOUT.byteSize() == 7; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceAssociationDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceAssociationDescriptor.java index e5f343f8..b2b14350 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceAssociationDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceAssociationDescriptor.java @@ -9,16 +9,14 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; /** * USB interface association descriptor (IAD) */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class InterfaceAssociationDescriptor { private final MemorySegment descriptor; @@ -32,27 +30,27 @@ public InterfaceAssociationDescriptor(MemorySegment segment, long offset) { } public int firstInterface() { - return 0xff & (byte) bFirstInterface$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bFirstInterface$OFFSET); } public int interfaceCount() { - return 0xff & (byte) bInterfaceCount$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterfaceCount$OFFSET); } public int functionClass() { - return 0xff & (byte) bFunctionClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bFunctionClass$OFFSET); } public int functionSubClass() { - return 0xff & (byte) bFunctionSubClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bFunctionSubClass$OFFSET); } public int functionProtocol() { - return 0xff & (byte) bFunctionProtocol$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bFunctionProtocol$OFFSET); } public int function() { - return 0xff & (byte) iFunction$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, iFunction$OFFSET); } // struct USBInterfaceAssociationDescriptor { @@ -76,12 +74,12 @@ public int function() { JAVA_BYTE.withName("iFunction") ); - private static final VarHandle bFirstInterface$VH = LAYOUT.varHandle(groupElement("bFirstInterface")); - private static final VarHandle bInterfaceCount$VH = LAYOUT.varHandle(groupElement("bInterfaceCount")); - private static final VarHandle bFunctionClass$VH = LAYOUT.varHandle(groupElement("bFunctionClass")); - private static final VarHandle bFunctionSubClass$VH = LAYOUT.varHandle(groupElement("bFunctionSubClass")); - private static final VarHandle bFunctionProtocol$VH = LAYOUT.varHandle(groupElement("bFunctionProtocol")); - private static final VarHandle iFunction$VH = LAYOUT.varHandle(groupElement("iFunction")); + private static final long bFirstInterface$OFFSET = 2; + private static final long bInterfaceCount$OFFSET = 3; + private static final long bFunctionClass$OFFSET = 4; + private static final long bFunctionSubClass$OFFSET = 5; + private static final long bFunctionProtocol$OFFSET = 6; + private static final long iFunction$OFFSET = 7; static { assert LAYOUT.byteSize() == 8; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceDescriptor.java index faf0032b..27351670 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/InterfaceDescriptor.java @@ -9,16 +9,14 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; /** * USB interface descriptor */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class InterfaceDescriptor { private final MemorySegment descriptor; @@ -32,31 +30,31 @@ public InterfaceDescriptor(MemorySegment segment, long offset) { } public int interfaceNumber() { - return 0xff & (byte) bInterfaceNumber$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterfaceNumber$OFFSET); } public int alternateSetting() { - return 0xff & (byte) bAlternateSetting$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bAlternateSetting$OFFSET); } public int numEndpoints() { - return 0xff & (byte) bNumEndpoints$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bNumEndpoints$OFFSET); } public int interfaceClass() { - return 0xff & (byte) bInterfaceClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterfaceClass$OFFSET); } public int interfaceSubClass() { - return 0xff & (byte) bInterfaceSubClass$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterfaceSubClass$OFFSET); } public int interfaceProtocol() { - return 0xff & (byte) bInterfaceProtocol$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bInterfaceProtocol$OFFSET); } public int iInterface() { - return 0xff & (byte) iInterface$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, iInterface$OFFSET); } // struct USBInterfaceDescriptor { @@ -82,13 +80,13 @@ public int iInterface() { JAVA_BYTE.withName("iInterface") ); - private static final VarHandle bInterfaceNumber$VH = LAYOUT.varHandle(groupElement("bInterfaceNumber")); - private static final VarHandle bAlternateSetting$VH = LAYOUT.varHandle(groupElement("bAlternateSetting")); - private static final VarHandle bNumEndpoints$VH = LAYOUT.varHandle(groupElement("bNumEndpoints")); - private static final VarHandle bInterfaceClass$VH = LAYOUT.varHandle(groupElement("bInterfaceClass")); - private static final VarHandle bInterfaceSubClass$VH = LAYOUT.varHandle(groupElement("bInterfaceSubClass")); - private static final VarHandle bInterfaceProtocol$VH = LAYOUT.varHandle(groupElement("bInterfaceProtocol")); - private static final VarHandle iInterface$VH = LAYOUT.varHandle(groupElement("iInterface")); + private static final long bInterfaceNumber$OFFSET = 2; + private static final long bAlternateSetting$OFFSET = 3; + private static final long bNumEndpoints$OFFSET = 4; + private static final long bInterfaceClass$OFFSET = 5; + private static final long bInterfaceSubClass$OFFSET = 6; + private static final long bInterfaceProtocol$OFFSET = 7; + private static final long iInterface$OFFSET = 8; static { diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/SetupPacket.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/SetupPacket.java index c934631b..e907d42f 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/SetupPacket.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/SetupPacket.java @@ -3,9 +3,7 @@ import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.structLayout; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_SHORT; @@ -13,7 +11,7 @@ /** * USB setup packet. */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class SetupPacket { private final MemorySegment descriptor; @@ -46,43 +44,43 @@ public MemorySegment segment() { } public int requestType() { - return 0xff & (byte) bmRequestType$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bmRequestType$OFFSET); } public void setRequestType(int requestType) { - bmRequestType$VH.set(descriptor, (byte) requestType); + descriptor.set(JAVA_BYTE, bmRequestType$OFFSET, (byte) requestType); } public int request() { - return 0xff & (byte) bRequest$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bRequest$OFFSET); } public void setRequest(int request) { - bRequest$VH.set(descriptor, (byte) request); + descriptor.set(JAVA_BYTE, bRequest$OFFSET, (byte) request); } public int value() { - return 0xffff & (short) wValue$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT, wValue$OFFSET); } public void setValue(int value) { - wValue$VH.set(descriptor, (short) value); + descriptor.set(JAVA_SHORT, wValue$OFFSET, (short) value); } public int index() { - return 0xffff & (short) wIndex$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT, wIndex$OFFSET); } public void setIndex(int index) { - wIndex$VH.set(descriptor, (short) index); + descriptor.set(JAVA_SHORT, wIndex$OFFSET, (short) index); } public int length() { - return 0xffff & (short) wLength$VH.get(descriptor); + return 0xffff & descriptor.get(JAVA_SHORT, wLength$OFFSET); } public void setLength(int length) { - wLength$VH.set(descriptor, (short) length); + descriptor.set(JAVA_SHORT, wLength$OFFSET, (short) length); } // struct USBSetupPacket { @@ -100,11 +98,11 @@ public void setLength(int length) { JAVA_SHORT.withName("wLength") ); - private static final VarHandle bmRequestType$VH = LAYOUT.varHandle(groupElement("bmRequestType")); - private static final VarHandle bRequest$VH = LAYOUT.varHandle(groupElement("bRequest")); - private static final VarHandle wValue$VH = LAYOUT.varHandle(groupElement("wValue")); - private static final VarHandle wIndex$VH = LAYOUT.varHandle(groupElement("wIndex")); - private static final VarHandle wLength$VH = LAYOUT.varHandle(groupElement("wLength")); + private static final long bmRequestType$OFFSET = 0; + private static final long bRequest$OFFSET = 1; + private static final long wValue$OFFSET = 2; + private static final long wIndex$OFFSET = 4; + private static final long wLength$OFFSET = 6; static { assert LAYOUT.byteSize() == 8; diff --git a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/StringDescriptor.java b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/StringDescriptor.java index 4863045f..a324e531 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/StringDescriptor.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/usbstandard/StringDescriptor.java @@ -7,18 +7,20 @@ package net.codecrete.usb.usbstandard; +import net.codecrete.usb.UsbException; + import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.invoke.VarHandle; +import java.nio.charset.StandardCharsets; -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; /** * USB string descriptor */ -@SuppressWarnings("java:S125") +@SuppressWarnings({"java:S115", "java:S125"}) public class StringDescriptor { private final MemorySegment descriptor; @@ -27,13 +29,46 @@ public StringDescriptor(MemorySegment descriptor) { this.descriptor = descriptor; } + /** + * Indicates if this string descriptor is valid. + *

+ * Invalid string descriptors might be missing the header, + * have a descriptor type that is not a string descriptor, + * indicate an incorrect length or have incomplete UTF-16 code units. + *

+ * @return if this descriptor is valid + */ + public boolean isValid() { + return descriptor.byteSize() >= 2 + && descriptor.get(JAVA_BYTE, bDescriptorType$OFFSET) == 3 + && length() == descriptor.byteSize() + && (descriptor.byteSize() & 1) == 0; + } + public int length() { - return 0xff & (byte) bLength$VH.get(descriptor); + return 0xff & descriptor.get(JAVA_BYTE, bLength$OFFSET); } + /** + * Returns the string of this string descriptor. + *

+ * Invalid UTF-16 code units are replaced with the Unicode replacement character. + * Trailing 0s (UTF-16 code unit with value 0) are truncated. + *

+ * @throws UsbException if the string descriptor is invalid + * @return the string value + */ public String string() { - var chars = descriptor.asSlice(string$offset, length() - 2L).toArray(JAVA_CHAR); - return new String(chars); + if (!isValid()) + throw new UsbException("String descriptor is invalid"); + var len = (int) (length() - 2L); + var bytes = descriptor.asSlice(string$OFFSET, len).toArray(JAVA_BYTE); + + // truncate trailing 0s + while (len > 0 && bytes[len - 2] == 0 && bytes[len - 1] == 0) + len--; + + return new String(bytes, 0, len, StandardCharsets.UTF_16LE); } // struct USBStringDescriptor { @@ -47,6 +82,7 @@ public String string() { JAVA_SHORT.withName("string") ); - private static final VarHandle bLength$VH = LAYOUT.varHandle(groupElement("bLength")); - private static final long string$offset = LAYOUT.byteOffset(groupElement("string")); // NOSONAR + private static final long bLength$OFFSET = 0; + private static final long bDescriptorType$OFFSET = 1; + private static final long string$OFFSET = 2; } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/CustomApis.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/CustomApis.java new file mode 100644 index 00000000..34ecb727 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/CustomApis.java @@ -0,0 +1,58 @@ +package net.codecrete.usb.windows; + +import net.codecrete.usb.usbstandard.SetupPacket; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; + +@SuppressWarnings({"java:S100", "java:S101", "java:S112", "java:S117"}) +public class CustomApis { + private CustomApis() { + } + + static { + System.loadLibrary("KERNEL32"); + System.loadLibrary("WINUSB"); + } + + private static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup(); + private static final Linker LINKER = Linker.nativeLinker(); + private static final Linker.Option LAST_ERROR_STATE = Linker.Option.captureCallState("GetLastError"); + + // Custom implementation of WinUsb_ControlTransfer as FFM cannot deal with the + // WINUSB_SETUP_PACKET being passed by value as it uses unaligned fields. + // SetupPacket does not use unaligned fields. + private static class WinUsb_ControlTransfer$IMPL { + private static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT, ADDRESS, SetupPacket.LAYOUT, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); + private static final MethodHandle HANDLE = LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow("WinUsb_ControlTransfer"), DESC, LAST_ERROR_STATE); + } + + public static int WinUsb_ControlTransfer(MemorySegment lastErrorState, MemorySegment InterfaceHandle, MemorySegment SetupPacket, MemorySegment Buffer, int BufferLength, MemorySegment LengthTransferred, MemorySegment Overlapped) { + try { + return (int) WinUsb_ControlTransfer$IMPL.HANDLE.invokeExact(lastErrorState, InterfaceHandle, SetupPacket, Buffer, BufferLength, LengthTransferred, Overlapped); + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } + + // CloseHandle implementation without error state + private static class CloseHandle$IMPL { + private static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT, ADDRESS); + private static final MethodHandle HANDLE = LINKER.downcallHandle(SYMBOL_LOOKUP.findOrThrow("CloseHandle"), DESC); + } + + public static int CloseHandle(MemorySegment hObject) { + try { + return (int) CloseHandle$IMPL.HANDLE.invokeExact(hObject); + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceInfoSet.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceInfoSet.java index 623168f5..e9d3bfb8 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceInfoSet.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceInfoSet.java @@ -1,15 +1,10 @@ package net.codecrete.usb.windows; import net.codecrete.usb.common.ScopeCleanup; -import net.codecrete.usb.windows.gen.advapi32.Advapi32; -import net.codecrete.usb.windows.gen.kernel32.Kernel32; -import net.codecrete.usb.windows.gen.kernel32._GUID; -import net.codecrete.usb.windows.gen.ole32.Ole32; -import net.codecrete.usb.windows.gen.setupapi.SetupAPI; -import net.codecrete.usb.windows.gen.setupapi._SP_DEVICE_INTERFACE_DATA; -import net.codecrete.usb.windows.gen.setupapi._SP_DEVICE_INTERFACE_DETAIL_DATA_W; -import net.codecrete.usb.windows.gen.setupapi._SP_DEVINFO_DATA; -import net.codecrete.usb.windows.winsdk.SetupAPI2; +import system.Guid; +import windows.win32.devices.deviceanddriverinstallation.SP_DEVICE_INTERFACE_DATA; +import windows.win32.devices.deviceanddriverinstallation.SP_DEVICE_INTERFACE_DETAIL_DATA_W; +import windows.win32.devices.deviceanddriverinstallation.SP_DEVINFO_DATA; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -18,10 +13,38 @@ import static java.lang.foreign.MemorySegment.NULL; import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static java.lang.foreign.ValueLayout.JAVA_INT; -import static net.codecrete.usb.windows.DevicePropertyKey.Service; +import static java.nio.charset.StandardCharsets.UTF_16LE; import static net.codecrete.usb.windows.Win.allocateErrorState; -import static net.codecrete.usb.windows.WindowsUSBException.throwException; -import static net.codecrete.usb.windows.WindowsUSBException.throwLastError; +import static net.codecrete.usb.windows.WindowsUsbException.throwException; +import static net.codecrete.usb.windows.WindowsUsbException.throwLastError; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiDeleteDeviceInterfaceData; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiDestroyDeviceInfoList; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiEnumDeviceInfo; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiEnumDeviceInterfaces; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiGetClassDevsW; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiCreateDeviceInfoList; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiGetDeviceInterfaceDetailW; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiGetDevicePropertyW; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiOpenDevRegKey; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiOpenDeviceInfoW; +import static windows.win32.devices.deviceanddriverinstallation.Apis.SetupDiOpenDeviceInterfaceW; +import static windows.win32.devices.deviceanddriverinstallation.Constants.DIREG_DEV; +import static windows.win32.devices.deviceanddriverinstallation.SETUP_DI_GET_CLASS_DEVS_FLAGS.DIGCF_DEVICEINTERFACE; +import static windows.win32.devices.deviceanddriverinstallation.SETUP_DI_GET_CLASS_DEVS_FLAGS.DIGCF_PRESENT; +import static windows.win32.devices.deviceanddriverinstallation.SETUP_DI_PROPERTY_CHANGE_SCOPE.DICS_FLAG_GLOBAL; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_Service; +import static windows.win32.devices.properties.DEVPROPTYPE.DEVPROP_TYPEMOD_LIST; +import static windows.win32.devices.properties.DEVPROPTYPE.DEVPROP_TYPE_STRING; +import static windows.win32.devices.properties.DEVPROPTYPE.DEVPROP_TYPE_UINT32; +import static windows.win32.foundation.WIN32_ERROR.ERROR_FILE_NOT_FOUND; +import static windows.win32.foundation.WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER; +import static windows.win32.foundation.WIN32_ERROR.ERROR_MORE_DATA; +import static windows.win32.foundation.WIN32_ERROR.ERROR_NOT_FOUND; +import static windows.win32.foundation.WIN32_ERROR.ERROR_NO_MORE_ITEMS; +import static windows.win32.system.com.Apis.CLSIDFromString; +import static windows.win32.system.registry.Apis.RegCloseKey; +import static windows.win32.system.registry.Apis.RegQueryValueExW; +import static windows.win32.system.registry.REG_SAM_FLAGS.KEY_READ; /** * Device information set (of Windows Setup API). @@ -35,12 +58,12 @@ public class DeviceInfoSet implements AutoCloseable { @FunctionalInterface interface InfoSetCreator { - MemorySegment create(Arena arena, MemorySegment errorState); + long create(Arena arena, MemorySegment errorState); } private final Arena arena; private final MemorySegment errorState; - private final MemorySegment devInfoSet; + private final long devInfoSet; private final MemorySegment devInfoData; private MemorySegment devIntfData; private int iterationIndex = -1; @@ -60,9 +83,9 @@ interface InfoSetCreator { */ static DeviceInfoSet ofPresentDevices(MemorySegment interfaceGuid, String instanceId) { return new DeviceInfoSet((arena, errorState) -> { - var instanceIdSegment = instanceId != null ? Win.createSegmentFromString(instanceId, arena) : NULL; - return SetupAPI2.SetupDiGetClassDevsW(interfaceGuid, instanceIdSegment, NULL, - SetupAPI.DIGCF_PRESENT() | SetupAPI.DIGCF_DEVICEINTERFACE(), errorState); + var instanceIdSegment = instanceId != null ? arena.allocateFrom(instanceId, UTF_16LE) : NULL; + return SetupDiGetClassDevsW(errorState, interfaceGuid, instanceIdSegment, NULL, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); }); } @@ -77,7 +100,12 @@ static DeviceInfoSet ofPresentDevices(MemorySegment interfaceGuid, String instan */ static DeviceInfoSet ofInstance(String instanceId) { var devInfoSet = ofEmpty(); - devInfoSet.addInstanceId(instanceId); + try { + devInfoSet.addInstanceId(instanceId); + } catch (Exception t) { + devInfoSet.close(); + throw t; + } return devInfoSet; } @@ -92,7 +120,12 @@ static DeviceInfoSet ofInstance(String instanceId) { */ static DeviceInfoSet ofPath(String devicePath) { var devInfoSet = ofEmpty(); - devInfoSet.addDevicePath(devicePath); + try { + devInfoSet.addDevicePath(devicePath); + } catch (Exception t) { + devInfoSet.close(); + throw t; + } return devInfoSet; } @@ -102,7 +135,7 @@ static DeviceInfoSet ofPath(String devicePath) { * @return device info set */ private static DeviceInfoSet ofEmpty() { - return new DeviceInfoSet((arena, errorState) -> SetupAPI2.SetupDiCreateDeviceInfoList(NULL, NULL, errorState)); + return new DeviceInfoSet((_, errorState) -> SetupDiCreateDeviceInfoList(errorState, NULL, NULL)); } private DeviceInfoSet(InfoSetCreator creator) { @@ -115,8 +148,7 @@ private DeviceInfoSet(InfoSetCreator creator) { throwLastError(errorState, "internal error (creating device info set)"); // allocate SP_DEVINFO_DATA (will receive device details) - devInfoData = _SP_DEVINFO_DATA.allocate(arena); - _SP_DEVINFO_DATA.cbSize$set(devInfoData, (int) _SP_DEVINFO_DATA.$LAYOUT().byteSize()); + devInfoData = SP_DEVINFO_DATA.allocate(arena); } catch (Exception e) { arena.close(); @@ -127,14 +159,14 @@ private DeviceInfoSet(InfoSetCreator creator) { @Override public void close() { if (devIntfData != null) - SetupAPI.SetupDiDeleteDeviceInterfaceData(devInfoSet, devIntfData); - SetupAPI.SetupDiDestroyDeviceInfoList(devInfoSet); + SetupDiDeleteDeviceInterfaceData(errorState, devInfoSet, devIntfData); + SetupDiDestroyDeviceInfoList(errorState, devInfoSet); arena.close(); } private void addInstanceId(String instanceId) { - var instanceIdSegment = Win.createSegmentFromString(instanceId, arena); - if (SetupAPI2.SetupDiOpenDeviceInfoW(devInfoSet, instanceIdSegment, NULL, 0, devInfoData, errorState) == 0) + var instanceIdSegment = arena.allocateFrom(instanceId, UTF_16LE); + if (SetupDiOpenDeviceInfoW(errorState, devInfoSet, instanceIdSegment, NULL, 0, devInfoData) == 0) throwLastError(errorState, "internal error (SetupDiOpenDeviceInfoW)"); } @@ -143,18 +175,16 @@ private void addDevicePath(String devicePath) { throw new AssertionError("calling addDevice() multiple times is not implemented"); // load device information into dev info set - var intfData = _SP_DEVICE_INTERFACE_DATA.allocate(arena); - _SP_DEVICE_INTERFACE_DATA.cbSize$set(intfData, (int) intfData.byteSize()); - var devicePathSegment = Win.createSegmentFromString(devicePath, arena); - if (SetupAPI2.SetupDiOpenDeviceInterfaceW(devInfoSet, devicePathSegment, 0, intfData, errorState) == 0) + var intfData = SP_DEVICE_INTERFACE_DATA.allocate(arena); + var devicePathSegment = arena.allocateFrom(devicePath, UTF_16LE); + if (SetupDiOpenDeviceInterfaceW(errorState, devInfoSet, devicePathSegment, 0, intfData) == 0) throwLastError(errorState, "internal error (SetupDiOpenDeviceInterfaceW)"); devIntfData = intfData; // for later cleanup - if (SetupAPI2.SetupDiGetDeviceInterfaceDetailW(devInfoSet, intfData, NULL, 0, NULL, - devInfoData, errorState) == 0) { + if (SetupDiGetDeviceInterfaceDetailW(errorState, devInfoSet, intfData, NULL, 0, NULL, devInfoData) == 0) { var err = Win.getLastError(errorState); - if (err != Kernel32.ERROR_INSUFFICIENT_BUFFER()) + if (err != ERROR_INSUFFICIENT_BUFFER) throwException(err, "internal error (SetupDiGetDeviceInterfaceDetailW)"); } } @@ -166,9 +196,9 @@ private void addDevicePath(String devicePath) { */ boolean next() { iterationIndex += 1; - if (SetupAPI2.SetupDiEnumDeviceInfo(devInfoSet, iterationIndex, devInfoData, errorState) == 0) { + if (SetupDiEnumDeviceInfo(errorState, devInfoSet, iterationIndex, devInfoData) == 0) { var err = Win.getLastError(errorState); - if (err == Kernel32.ERROR_NO_MORE_ITEMS()) + if (err == ERROR_NO_MORE_ITEMS) return false; throwLastError(errorState, "internal error (SetupDiEnumDeviceInfo)"); } @@ -182,7 +212,7 @@ boolean next() { * @return {@code true} if it is a composite device */ boolean isCompositeDevice() { - var deviceService = getStringProperty(Service); + var deviceService = getStringProperty(DEVPKEY_Device_Service()); // usbccgp is the USB Generic Parent Driver used for composite devices return "usbccgp".equalsIgnoreCase(deviceService); @@ -202,14 +232,14 @@ String getDevicePathByGUID(String instanceId) { for (var guid : guids) { // check for class GUID - var guidSegment = Win.createSegmentFromString(guid, arena); - var clsid = _GUID.allocate(arena); - if (Ole32.CLSIDFromString(guidSegment, clsid) != 0) + var guidSegment = arena.allocateFrom(guid, UTF_16LE); + var clsid = Guid.allocate(arena); + if (CLSIDFromString(guidSegment, clsid) != 0) continue; try { return getDevicePath(instanceId, clsid); - } catch (Exception e) { + } catch (Exception _) { // ignore and try next one } } @@ -228,26 +258,26 @@ private List findDeviceInterfaceGUIDs(Arena arena) { try (var cleanup = new ScopeCleanup()) { // open device registry key - var regKey = SetupAPI2.SetupDiOpenDevRegKey(devInfoSet, devInfoData, SetupAPI.DICS_FLAG_GLOBAL(), 0, - SetupAPI.DIREG_DEV(), Advapi32.KEY_READ(), errorState); + var regKey = SetupDiOpenDevRegKey(errorState, devInfoSet, devInfoData, DICS_FLAG_GLOBAL, 0, + DIREG_DEV, KEY_READ); if (Win.isInvalidHandle(regKey)) throwLastError(errorState, "internal error (SetupDiOpenDevRegKey)"); - cleanup.add(() -> Advapi32.RegCloseKey(regKey)); + cleanup.add(() -> RegCloseKey(regKey)); // read registry value (without buffer, to query length) - var keyNameSegment = Win.createSegmentFromString("DeviceInterfaceGUIDs", arena); + var keyNameSegment = arena.allocateFrom("DeviceInterfaceGUIDs", UTF_16LE); var valueTypeHolder = arena.allocate(JAVA_INT); var valueSizeHolder = arena.allocate(JAVA_INT); - var res = Advapi32.RegQueryValueExW(regKey, keyNameSegment, NULL, valueTypeHolder, NULL, valueSizeHolder); - if (res == Kernel32.ERROR_FILE_NOT_FOUND()) + var res = RegQueryValueExW(regKey, keyNameSegment, NULL, valueTypeHolder, NULL, valueSizeHolder); + if (res == ERROR_FILE_NOT_FOUND) return List.of(); // no device interface GUIDs - if (res != 0 && res != Kernel32.ERROR_MORE_DATA()) + if (res != 0 && res != ERROR_MORE_DATA) throwException(res, "internal error (RegQueryValueExW)"); // read registry value (with buffer) var valueSize = valueSizeHolder.get(JAVA_INT, 0); var value = arena.allocate(valueSize); - res = Advapi32.RegQueryValueExW(regKey, keyNameSegment, NULL, valueTypeHolder, value, valueSizeHolder); + res = RegQueryValueExW(regKey, keyNameSegment, NULL, valueTypeHolder, value, valueSizeHolder); if (res != 0) throwException(res, "internal error (RegQueryValueExW)"); @@ -265,11 +295,11 @@ private List findDeviceInterfaceGUIDs(Arena arena) { int getIntProperty(MemorySegment propertyKey) { var propertyTypeHolder = arena.allocate(JAVA_INT); var propertyValueHolder = arena.allocate(JAVA_INT); - if (SetupAPI2.SetupDiGetDevicePropertyW(devInfoSet, devInfoData, propertyKey, propertyTypeHolder, - propertyValueHolder, (int) propertyValueHolder.byteSize(), NULL, 0, errorState) == 0) + if (SetupDiGetDevicePropertyW(errorState, devInfoSet, devInfoData, propertyKey, propertyTypeHolder, + propertyValueHolder, (int) propertyValueHolder.byteSize(), NULL, 0) == 0) throwLastError(errorState, "internal error (SetupDiGetDevicePropertyW - A)"); - if (propertyTypeHolder.get(JAVA_INT, 0) != SetupAPI.DEVPROP_TYPE_UINT32()) + if (propertyTypeHolder.get(JAVA_INT, 0) != DEVPROP_TYPE_UINT32) throwException("internal error (expected property type UINT32)"); return propertyValueHolder.get(JAVA_INT, 0); @@ -282,10 +312,10 @@ int getIntProperty(MemorySegment propertyKey) { * @return property value */ String getStringProperty(MemorySegment propertyKey) { - var propertyValue = getVariableLengthProperty(propertyKey, SetupAPI.DEVPROP_TYPE_STRING(), arena); + var propertyValue = getVariableLengthProperty(propertyKey, DEVPROP_TYPE_STRING, arena); if (propertyValue == null) return null; - return Win.createStringFromSegment(propertyValue); + return propertyValue.getString(0, UTF_16LE); } /** @@ -297,7 +327,7 @@ String getStringProperty(MemorySegment propertyKey) { @SuppressWarnings("java:S1168") List getStringListProperty(MemorySegment propertyKey) { var propertyValue = getVariableLengthProperty(propertyKey, - SetupAPI.DEVPROP_TYPE_STRING() | SetupAPI.DEVPROP_TYPEMOD_LIST(), arena); + DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST, arena); if (propertyValue == null) return null; @@ -309,26 +339,26 @@ private MemorySegment getVariableLengthProperty(MemorySegment propertyKey, int p // query length (thus no buffer) var propertyTypeHolder = arena.allocate(JAVA_INT); var requiredSizeHolder = arena.allocate(JAVA_INT); - if (SetupAPI2.SetupDiGetDevicePropertyW(devInfoSet, devInfoData, propertyKey, propertyTypeHolder, NULL, 0, - requiredSizeHolder, 0, errorState) == 0) { + if (SetupDiGetDevicePropertyW(errorState, devInfoSet, devInfoData, propertyKey, propertyTypeHolder, NULL, 0, + requiredSizeHolder, 0) == 0) { var err = Win.getLastError(errorState); - if (err == Kernel32.ERROR_NOT_FOUND()) + if (err == ERROR_NOT_FOUND) return null; - if (err != Kernel32.ERROR_INSUFFICIENT_BUFFER()) + if (err != ERROR_INSUFFICIENT_BUFFER) throwException(err, "internal error (SetupDiGetDevicePropertyW - B)"); } if (propertyTypeHolder.get(JAVA_INT, 0) != propertyType) throwException("internal error (unexpected property type)"); - var stringLen = requiredSizeHolder.get(JAVA_INT, 0) / 2 - 1; + var stringLen = (requiredSizeHolder.get(JAVA_INT, 0) + 1) / 2; // allocate buffer - var propertyValueHolder = arena.allocateArray(JAVA_CHAR, stringLen + 1L); + var propertyValueHolder = arena.allocate(JAVA_CHAR, stringLen); // get property value - if (SetupAPI2.SetupDiGetDevicePropertyW(devInfoSet, devInfoData, propertyKey, propertyTypeHolder, - propertyValueHolder, (int) propertyValueHolder.byteSize(), NULL, 0, errorState) == 0) + if (SetupDiGetDevicePropertyW(errorState, devInfoSet, devInfoData, propertyKey, propertyTypeHolder, + propertyValueHolder, (int) propertyValueHolder.byteSize(), NULL, 0) == 0) throwLastError(errorState, "internal error (SetupDiGetDevicePropertyW - C)"); return propertyValueHolder; @@ -342,29 +372,24 @@ private MemorySegment getVariableLengthProperty(MemorySegment propertyKey, int p * @return the device path */ static String getDevicePath(String instanceId, MemorySegment interfaceGuid) { - try (var arena = Arena.ofConfined(); - var deviceInfoSet = DeviceInfoSet.ofPresentDevices(interfaceGuid, instanceId)) { - - // retrieve first element of enumeration - var errorState = allocateErrorState(arena); - var devIntfData = _SP_DEVICE_INTERFACE_DATA.allocate(arena); - _SP_DEVICE_INTERFACE_DATA.cbSize$set(devIntfData, (int) devIntfData.byteSize()); - if (SetupAPI2.SetupDiEnumDeviceInterfaces(deviceInfoSet.devInfoSet, NULL, interfaceGuid, 0, devIntfData, - errorState) == 0) - throwLastError(errorState, "internal error (SetupDiEnumDeviceInterfaces)"); - - // get device path - // (SP_DEVICE_INTERFACE_DETAIL_DATA_W is of variable length and requires a bigger allocation so - // the device path fits) - final var devicePathOffset = 4; - var intfDetailData = arena.allocate(4L + 260 * 2); - _SP_DEVICE_INTERFACE_DETAIL_DATA_W.cbSize$set(intfDetailData, - (int) _SP_DEVICE_INTERFACE_DETAIL_DATA_W.sizeof()); - if (SetupAPI2.SetupDiGetDeviceInterfaceDetailW(deviceInfoSet.devInfoSet, devIntfData, intfDetailData, - (int) intfDetailData.byteSize(), NULL, NULL, errorState) == 0) - throwLastError(errorState, "Internal error (SetupDiGetDeviceInterfaceDetailW)"); - - return Win.createStringFromSegment(intfDetailData.asSlice(devicePathOffset)); + try (var deviceInfoSet = DeviceInfoSet.ofPresentDevices(interfaceGuid, instanceId)) { + return deviceInfoSet.getDevicePathForGuid(interfaceGuid); } } + + private String getDevicePathForGuid(MemorySegment interfaceGuid) { + // retrieve first element of enumeration + devIntfData = SP_DEVICE_INTERFACE_DATA.allocate(arena); + if (SetupDiEnumDeviceInterfaces(errorState, devInfoSet, NULL, interfaceGuid, 0, devIntfData) == 0) + throwLastError(errorState, "internal error (SetupDiEnumDeviceInterfaces)"); + + // get device path + var intfDetailData = SP_DEVICE_INTERFACE_DETAIL_DATA_W.allocate(arena, 260); + if (SetupDiGetDeviceInterfaceDetailW(errorState, devInfoSet, devIntfData, intfDetailData, + (int) intfDetailData.byteSize(), NULL, NULL) == 0) + throwLastError(errorState, "Internal error (SetupDiGetDeviceInterfaceDetailW)"); + + var devicePath = SP_DEVICE_INTERFACE_DETAIL_DATA_W.DevicePath(intfDetailData); + return devicePath.getString(0, UTF_16LE); + } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/DevicePropertyKey.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/DevicePropertyKey.java deleted file mode 100644 index 72b97501..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/DevicePropertyKey.java +++ /dev/null @@ -1,77 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.windows; - -import net.codecrete.usb.windows.gen.setupapi._DEVPROPKEY; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; - -/** - * Device property keys (GUIDs) - */ -class DevicePropertyKey { - - private DevicePropertyKey() { - } - - /** - * DEVPKEY_Device_Address - */ - static final MemorySegment Address = createDEVPROPKEY(0xa45c254e, (short) 0xdf1c, - (short) 0x4efd, (byte) 0x80, (byte) 0x20, (byte) 0x67, (byte) 0xd1, (byte) 0x46, (byte) 0xa8, (byte) 0x50 - , (byte) 0xe0, 30); - - /** - * DEVPKEY_Device_InstanceId - */ - static final MemorySegment InstanceId = createDEVPROPKEY(0x78c34fc8, (short) 0x104a, - (short) 0x4aca, (byte) 0x9e, (byte) 0xa4, (byte) 0x52, (byte) 0x4d, (byte) 0x52, (byte) 0x99, (byte) 0x6e - , (byte) 0x57, 256); - - /** - * DEVPKEY_Device_Parent - */ - static final MemorySegment Parent = createDEVPROPKEY(0x4340a6c5, (short) 0x93fa, - (short) 0x4706, (byte) 0x97, (byte) 0x2c, (byte) 0x7b, (byte) 0x64, (byte) 0x80, (byte) 0x08, (byte) 0xa5 - , (byte) 0xa7, 8); - - /** - * DEVPKEY_Device_Service - */ - static final MemorySegment Service = createDEVPROPKEY(0xa45c254e, (short) 0xdf1c, - (short) 0x4efd, (byte) 0x80, (byte) 0x20, (byte) 0x67, (byte) 0xd1, (byte) 0x46, (byte) 0xa8, (byte) 0x50 - , (byte) 0xe0, 6); - - /** - * DEVPKEY_Device_Children - */ - static final MemorySegment Children = createDEVPROPKEY(0x4340a6c5, (short) 0x93fa, - (short) 0x4706, (byte) 0x97, (byte) 0x2c, (byte) 0x7b, (byte) 0x64, (byte) 0x80, (byte) 0x08, (byte) 0xa5 - , (byte) 0xa7, 9); - - /** - * DEVPKEY_Device_HardwareIds - */ - static final MemorySegment HardwareIds = createDEVPROPKEY(0xa45c254e, (short) 0xdf1c, - (short) 0x4efd, (byte) 0x80, (byte) 0x20, (byte) 0x67, (byte) 0xd1, (byte) 0x46, (byte) 0xa8, (byte) 0x50 - , (byte) 0xe0, 3); - - - @SuppressWarnings({"java:S107", "java:S117"}) - private static MemorySegment createDEVPROPKEY(int data1, short data2, short data3, byte data4_0, byte data4_1, - byte data4_2, byte data4_3, byte data4_4, byte data4_5, - byte data4_6, byte data4_7, int pid) { - @SuppressWarnings("resource") - var propKey = Arena.global().allocate(_DEVPROPKEY.$LAYOUT()); - Win.setGUID(_DEVPROPKEY.fmtid$slice(propKey), data1, data2, data3, data4_0, data4_1, data4_2, data4_3, data4_4 - , data4_5, data4_6, data4_7); - _DEVPROPKEY.pid$set(propKey, pid); - return propKey; - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/InterfaceHandle.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/InterfaceHandle.java index 91cc9bd4..c3d56a74 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/InterfaceHandle.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/InterfaceHandle.java @@ -13,21 +13,19 @@ * Handles for WinUSB devices and interfaces */ class InterfaceHandle { + InterfaceHandle(int interfaceNumber, int firstInterfaceNumber) { + this.interfaceNumber = interfaceNumber; + this.firstInterfaceNumber = firstInterfaceNumber; + } + /** * The number of this interface. */ - int interfaceNumber; + final int interfaceNumber; /** * The number of the first interface in the same composite function. */ - int firstInterfaceNumber; - /** - * The device path. - *

- * This is only set for the first interface in a composite function. - *

- */ - String devicePath; + final int firstInterfaceNumber; /** * The file handle of the device. *

@@ -39,7 +37,7 @@ class InterfaceHandle { * The WinUSB handle of the interface. */ @SuppressWarnings("java:S1700") - MemorySegment interfaceHandle; + MemorySegment winusbHandle; /** * Count indicating how many interface depend on the device being open. */ diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/USBConstants.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/USBConstants.java deleted file mode 100644 index c4e18577..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/USBConstants.java +++ /dev/null @@ -1,32 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.windows; - -import java.lang.foreign.MemorySegment; - -/** - * USB constants (general ones and Windows specific ones) - */ -@SuppressWarnings({"java:S125", "java:S1192", "java:S115", "java:S100"}) -class USBConstants { - - private USBConstants() { - } - - static final byte USB_REQUEST_GET_DESCRIPTOR = 0x06; - - // A5DCBF10-6530-11D2-901F-00C04FB951ED - static final MemorySegment GUID_DEVINTERFACE_USB_DEVICE = Win.createGUID(0xA5DCBF10, (short) 0x6530, - (short) 0x11D2, (byte) 0x90, (byte) 0x1F, (byte) 0x00, (byte) 0xC0, (byte) 0x4F, (byte) 0xB9, (byte) 0x51 - , (byte) 0xED); - - // f18a0e88-c30c-11d0-8815-00a0c906bed8 - static final MemorySegment GUID_DEVINTERFACE_USB_HUB = Win.createGUID(0xf18a0e88, (short) 0xc30c, - (short) 0x11d0, (byte) 0x88, (byte) 0x15, (byte) 0x00, (byte) 0xa0, (byte) 0xc9, (byte) 0x06, (byte) 0xbe - , (byte) 0xd8); -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/Win.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/Win.java index 1bea7e6d..6f5791bf 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/Win.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/Win.java @@ -7,16 +7,17 @@ package net.codecrete.usb.windows; -import net.codecrete.usb.windows.gen.kernel32._GUID; - -import java.lang.foreign.*; +import java.lang.foreign.Arena; +import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.StructLayout; import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_CHAR; +import static java.nio.charset.StandardCharsets.UTF_16LE; /** * Windows helpers. @@ -45,7 +46,7 @@ static MemorySegment allocateErrorState(Arena arena) { * @return the error code */ public static int getLastError(MemorySegment callState) { - return (int) callState_GetLastError$VH.get(callState); + return (int) callState_GetLastError$VH.get(callState, 0); } /** @@ -59,45 +60,19 @@ public static boolean isInvalidHandle(MemorySegment handle) { } /** - * Creates a memory segment as a copy of a Java string. - *

- * The memory segment contains a copy of the string (null-terminated, UTF-16/wide characters). - *

- * - * @param str the string to copy - * @param arena the arena for the memory segment - * @return the resulting memory segment - */ - public static MemorySegment createSegmentFromString(String str, Arena arena) { - // allocate segment (including space for terminating null) - var segment = arena.allocateArray(ValueLayout.JAVA_CHAR, str.length() + 1L); - // copy characters - segment.copyFrom(MemorySegment.ofArray(str.toCharArray())); - return segment; - } - - /** - * Creates a copy of the string in the memory segment. - *

- * The string must be a null-terminated UTF-16 (wide character) string. - *

+ * Checks if a Windows handle is invalid. * - * @param segment the memory segment - * @return copied string + * @param handle Windows handle + * @return {@code true} if the handle is invalid, {@code false} otherwise */ - public static String createStringFromSegment(MemorySegment segment) { - var len = 0; - while (segment.get(JAVA_CHAR, len) != 0) { - len += 2; - } - - return new String(segment.asSlice(0, len).toArray(JAVA_CHAR)); + public static boolean isInvalidHandle(long handle) { + return handle == -1L; } /** * Creates a copy of the string list in the memory segment. *

- * The string list a a series of null-terminated UTF-16 (wide character) strings. + * The string list is a series of null-terminated UTF-16 (wide character) strings. * The list is terminated with yet another null character. *

* @@ -108,53 +83,10 @@ public static List createStringListFromSegment(MemorySegment segment) { var stringList = new ArrayList(); var offset = 0; while (segment.get(JAVA_CHAR, offset) != '\0') { - var str = Win.createStringFromSegment(segment.asSlice(offset)); + var str = segment.getString(offset, UTF_16LE); offset += str.length() * 2 + 2; stringList.add(str); } return stringList; } - - /** - * Creates a GUID in native memory. - * - * @param data1 Group 1 (4 bytes). - * @param data2 Group 2 (2 bytes). - * @param data3 Group 3 (2 bytes). - * @param data4_0 Byte 0 of group 4 - * @param data4_1 Byte 1 of group 4 - * @param data4_2 Byte 2 of group 4 - * @param data4_3 Byte 3 of group 4 - * @param data4_4 Byte 4 of group 4 - * @param data4_5 Byte 5 of group 4 - * @param data4_6 Byte 6 of group 4 - * @param data4_7 Byte 7 of group 4 - * @return GUID as memory segment - */ - @SuppressWarnings({"java:S117", "java:S107"}) - public static MemorySegment createGUID(int data1, short data2, short data3, byte data4_0, byte data4_1, - byte data4_2, byte data4_3, byte data4_4, byte data4_5, byte data4_6, - byte data4_7) { - @SuppressWarnings("resource") - var guid = Arena.global().allocate(_GUID.$LAYOUT()); - setGUID(guid, data1, data2, data3, data4_0, data4_1, data4_2, data4_3, data4_4, data4_5, data4_6, data4_7); - return guid; - } - - @SuppressWarnings({"java:S117", "java:S107"}) - public static void setGUID(MemorySegment guid, int data1, short data2, short data3, byte data4_0, byte data4_1, - byte data4_2, byte data4_3, byte data4_4, byte data4_5, byte data4_6, byte data4_7) { - _GUID.Data1$set(guid, data1); - _GUID.Data2$set(guid, data2); - _GUID.Data3$set(guid, data3); - var data4 = _GUID.Data4$slice(guid); - data4.set(JAVA_BYTE, 0, data4_0); - data4.set(JAVA_BYTE, 1, data4_1); - data4.set(JAVA_BYTE, 2, data4_2); - data4.set(JAVA_BYTE, 3, data4_3); - data4.set(JAVA_BYTE, 4, data4_4); - data4.set(JAVA_BYTE, 5, data4_5); - data4.set(JAVA_BYTE, 6, data4_6); - data4.set(JAVA_BYTE, 7, data4_7); - } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsAsyncTask.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsAsyncTask.java index 3a509650..fa31dad2 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsAsyncTask.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsAsyncTask.java @@ -7,9 +7,8 @@ package net.codecrete.usb.windows; -import net.codecrete.usb.windows.gen.kernel32.Kernel32; -import net.codecrete.usb.windows.gen.kernel32._OVERLAPPED; -import net.codecrete.usb.windows.winsdk.Kernel32B; +import net.codecrete.usb.UsbException; +import windows.win32.system.io.OVERLAPPED; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -18,10 +17,17 @@ import java.util.List; import java.util.Map; +import static java.lang.System.Logger.Level.ERROR; import static java.lang.foreign.MemorySegment.NULL; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; import static net.codecrete.usb.windows.Win.allocateErrorState; -import static net.codecrete.usb.windows.WindowsUSBException.throwLastError; +import static net.codecrete.usb.windows.WindowsUsbException.throwLastError; +import static windows.win32.foundation.WIN32_ERROR.ERROR_OPERATION_ABORTED; +import static windows.win32.system.io.Apis.CreateIoCompletionPort; +import static windows.win32.system.io.Apis.GetQueuedCompletionStatus; +import static windows.win32.system.threading.Constants.INFINITE; /** * Background task for handling asynchronous transfers. @@ -41,6 +47,8 @@ @SuppressWarnings("java:S6548") class WindowsAsyncTask { + private static final System.Logger LOG = System.getLogger(WindowsAsyncTask.class.getName()); + /** * Singleton instance of background task. */ @@ -59,33 +67,80 @@ class WindowsAsyncTask { */ private MemorySegment asyncIoCompletionPort = NULL; + /** + * Indicates that the background task has terminated due to an unrecoverable error. + */ + private boolean taskTerminated; + /** * Background task for handling asynchronous IO completions. */ + @SuppressWarnings("java:S2189") private void asyncCompletionTask() { try (var arena = Arena.ofConfined()) { - var overlappedHolder = arena.allocate(ADDRESS, NULL); - var numBytesHolder = arena.allocate(JAVA_INT, 0); - var completionKeyHolder = arena.allocate(JAVA_LONG, 0); + var overlappedHolder = arena.allocate(ADDRESS); + var numBytesHolder = arena.allocate(JAVA_INT); + var completionKeyHolder = arena.allocate(JAVA_LONG); var errorState = allocateErrorState(arena); while (true) { - overlappedHolder.set(ADDRESS, 0, NULL); - completionKeyHolder.set(JAVA_LONG, 0, 0); + try { + overlappedHolder.set(ADDRESS, 0, NULL); + completionKeyHolder.set(JAVA_LONG, 0, 0); - var res = Kernel32B.GetQueuedCompletionStatus(asyncIoCompletionPort, numBytesHolder, - completionKeyHolder, overlappedHolder, Kernel32.INFINITE(), errorState); - var overlappedAddr = overlappedHolder.get(JAVA_LONG, 0); + var res = GetQueuedCompletionStatus(errorState, asyncIoCompletionPort, numBytesHolder, + completionKeyHolder, overlappedHolder, INFINITE); + var overlappedAddr = overlappedHolder.get(JAVA_LONG, 0); - if (res == 0 && overlappedAddr == 0) - throwLastError(errorState, "internal error (SetupDiGetDeviceInterfaceDetailW)"); + // A null OVERLAPPED means no completion packet was dequeued (nothing posts + // packets without an OVERLAPPED): the completion port itself has failed, + // and no further completions will ever be delivered. + if (overlappedAddr == 0) { + var success = res != 0; + throwLastError(errorState, "internal error (GetQueuedCompletionStatus, success: %s)", success); + } - if (overlappedAddr == 0) - return; // registry closing? + completeTransfer(overlappedAddr); + + } catch (Exception e) { + LOG.log(ERROR, "USB async IO thread failed and is terminating; " + + "all outstanding transfers will fail, and no further transfers are possible", e); + failAllPendingTransfers(); + return; + } + } + } + } + + /** + * Fails all outstanding transfers and marks this task as terminated. + *

+ * Called when the background task can no longer dispatch completions. Waiters blocked + * on the failed transfers wake up with an error result instead of hanging forever, + * and future submissions are rejected. + *

+ */ + private void failAllPendingTransfers() { + List pendingTransfers; + synchronized (this) { + taskTerminated = true; + pendingTransfers = new ArrayList<>(requestsByOverlapped.values()); + requestsByOverlapped.clear(); + availableOverlappedStructs.clear(); + for (var transfer : pendingTransfers) { + transfer.setResultCode(ERROR_OPERATION_ABORTED); + transfer.setResultSize(0); + transfer.setOverlapped(null); + } + } - completeTransfer(overlappedAddr); + for (var transfer : pendingTransfers) { + try { + transfer.completion().completed(transfer); + } catch (Exception e) { + LOG.log(ERROR, "Unexpected exception while handling async IO completion", e); } } } @@ -104,8 +159,8 @@ synchronized void addDevice(MemorySegment handle) { var errorState = allocateErrorState(arena); // Creates a new port if it doesn't exist; adds handle to existing port if it exists - var portHandle = Kernel32B.CreateIoCompletionPort(handle, asyncIoCompletionPort, - handle.address(), 0, errorState); + var portHandle = CreateIoCompletionPort(errorState, handle, asyncIoCompletionPort, + handle.address(), 0); if (portHandle == MemorySegment.NULL) throwLastError(errorState, "internal error (CreateIoCompletionPort)"); @@ -133,10 +188,14 @@ private void startAsyncIOTask() { * @param transfer transfer to prepare */ synchronized void prepareForSubmission(WindowsTransfer transfer) { + if (taskTerminated) + throw new UsbException("USB async IO background thread has terminated due to an unrecoverable error; " + + "USB transfers are no longer possible"); + MemorySegment overlapped; var size = availableOverlappedStructs.size(); if (size == 0) { - overlapped = _OVERLAPPED.allocate(overlappedArena); + overlapped = OVERLAPPED.allocate(overlappedArena); } else { overlapped = availableOverlappedStructs.remove(size - 1); } @@ -146,21 +205,54 @@ synchronized void prepareForSubmission(WindowsTransfer transfer) { requestsByOverlapped.put(overlapped.address(), transfer); } + /** + * Undoes the registration performed by {@link #prepareForSubmission(WindowsTransfer)}. + *

+ * Must be called if the native submission of a prepared transfer fails synchronously. + * In that case, no completion packet will ever be posted for the transfer, so its map + * entry would leak and the OVERLAPPED struct would never return to the pool unless + * they are cleaned up here. + *

+ * + * @param transfer transfer whose submission failed + */ + synchronized void submissionFailed(WindowsTransfer transfer) { + requestsByOverlapped.remove(transfer.overlapped().address()); + availableOverlappedStructs.add(transfer.overlapped()); + transfer.setOverlapped(null); + } + /** * Completes the transfer by calling the completion handler. * * @param overlappedAddr address of OVERLAPPED struct */ - private synchronized void completeTransfer(long overlappedAddr) { - var transfer = requestsByOverlapped.remove(overlappedAddr); - if (transfer == null) - return; + private void completeTransfer(long overlappedAddr) { + WindowsTransfer transfer; + synchronized (this) { + transfer = requestsByOverlapped.remove(overlappedAddr); + if (transfer == null) + return; - transfer.setResultCode((int) _OVERLAPPED.Internal$get(transfer.overlapped())); - transfer.setResultSize((int) _OVERLAPPED.InternalHigh$get(transfer.overlapped())); + // the results must be read from the OVERLAPPED struct before it is + // returned to the pool and possibly reused by another submission + transfer.setResultCode((int) OVERLAPPED.Internal(transfer.overlapped())); + transfer.setResultSize((int) OVERLAPPED.InternalHigh(transfer.overlapped())); - availableOverlappedStructs.add(transfer.overlapped()); - transfer.setOverlapped(null); - transfer.completion().completed(transfer); + availableOverlappedStructs.add(transfer.overlapped()); + transfer.setOverlapped(null); + } + + // The completion handler must be called without holding the lock: handlers acquire + // other monitors (transfer, device), and threads submitting transfers acquire this + // task's lock while holding those monitors, so calling handlers under the lock can + // deadlock. + try { + transfer.completion().completed(transfer); + } catch (Exception e) { + // This method runs on the process-wide async IO thread. Any exception escaping + // would kill that thread and hang all async transfers for the entire library. + LOG.log(ERROR, "Unexpected exception while handling async IO completion", e); + } } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointInputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointInputStream.java index d331954e..0c96fc94 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointInputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointInputStream.java @@ -7,23 +7,23 @@ package net.codecrete.usb.windows; -import net.codecrete.usb.USBDirection; +import net.codecrete.usb.UsbDirection; import net.codecrete.usb.common.EndpointInputStream; import net.codecrete.usb.common.Transfer; public class WindowsEndpointInputStream extends EndpointInputStream { - WindowsEndpointInputStream(WindowsUSBDevice device, int endpointNumber, int bufferSize) { + WindowsEndpointInputStream(WindowsUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferIn(Transfer transfer) { - ((WindowsUSBDevice) device).submitTransferIn(endpointNumber, (WindowsTransfer) transfer); + ((WindowsUsbDevice) device).submitTransferIn(endpointNumber, (WindowsTransfer) transfer); } @Override protected void configureEndpoint() { - ((WindowsUSBDevice) device).configureForAsyncIo(USBDirection.IN, endpointNumber); + ((WindowsUsbDevice) device).configureForAsyncIo(UsbDirection.IN, endpointNumber); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointOutputStream.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointOutputStream.java index 46eb0f31..8125dd5a 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointOutputStream.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsEndpointOutputStream.java @@ -7,23 +7,23 @@ package net.codecrete.usb.windows; -import net.codecrete.usb.USBDirection; +import net.codecrete.usb.UsbDirection; import net.codecrete.usb.common.EndpointOutputStream; import net.codecrete.usb.common.Transfer; public class WindowsEndpointOutputStream extends EndpointOutputStream { - WindowsEndpointOutputStream(WindowsUSBDevice device, int endpointNumber, int bufferSize) { + WindowsEndpointOutputStream(WindowsUsbDevice device, int endpointNumber, int bufferSize) { super(device, endpointNumber, bufferSize); } @Override protected void submitTransferOut(Transfer request) { - ((WindowsUSBDevice) device).submitTransferOut(endpointNumber, (WindowsTransfer) request); + ((WindowsUsbDevice) device).submitTransferOut(endpointNumber, (WindowsTransfer) request); } @Override protected void configureEndpoint() { - ((WindowsUSBDevice) device).configureForAsyncIo(USBDirection.OUT, endpointNumber); + ((WindowsUsbDevice) device).configureForAsyncIo(UsbDirection.OUT, endpointNumber); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDevice.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDevice.java deleted file mode 100644 index ed7601fe..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDevice.java +++ /dev/null @@ -1,474 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.windows; - -import net.codecrete.usb.USBControlTransfer; -import net.codecrete.usb.USBDirection; -import net.codecrete.usb.USBRecipient; -import net.codecrete.usb.USBTransferType; -import net.codecrete.usb.common.Transfer; -import net.codecrete.usb.common.USBDeviceImpl; -import net.codecrete.usb.usbstandard.SetupPacket; -import net.codecrete.usb.windows.gen.kernel32.Kernel32; -import net.codecrete.usb.windows.gen.winusb.WinUSB; -import net.codecrete.usb.windows.winsdk.Kernel32B; -import net.codecrete.usb.windows.winsdk.WinUSB2; - -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static java.lang.foreign.MemorySegment.NULL; -import static java.lang.foreign.ValueLayout.*; -import static net.codecrete.usb.common.ForeignMemory.dereference; -import static net.codecrete.usb.windows.Win.allocateErrorState; -import static net.codecrete.usb.windows.WindowsUSBException.throwException; -import static net.codecrete.usb.windows.WindowsUSBException.throwLastError; - -/** - * Windows implementation for USB device. - */ -@SuppressWarnings("java:S2160") -public class WindowsUSBDevice extends USBDeviceImpl { - - private final WindowsAsyncTask asyncTask; - private List interfaceHandles; - /** - * Indicates if {@link #open()} has been called. Since separate interfaces can have separate underlying - * Windows device, {@link #claimInterface(int)} instead of {@link #open()} will open the Windows device. - */ - private boolean showAsOpen; - - WindowsUSBDevice(String devicePath, Map children, - int vendorId, int productId, MemorySegment configDesc) { - super(devicePath, vendorId, productId); - asyncTask = WindowsAsyncTask.INSTANCE; - readDescription(configDesc, devicePath, children); - } - - private void readDescription(MemorySegment configDesc, String devicePath, Map children) { - var configuration = setConfigurationDescriptor(configDesc); - - // build list of interface handles - interfaceHandles = new ArrayList<>(); - for (var intf : configuration.interfaces()) { - var interfaceNumber = intf.number(); - var function = configuration.findFunction(interfaceNumber); - - var intfHandle = new InterfaceHandle(); - intfHandle.interfaceNumber = interfaceNumber; - if (function.firstInterfaceNumber() == interfaceNumber) { - if (children == null) { - intfHandle.devicePath = devicePath; - } else { - intfHandle.devicePath = children.get(interfaceNumber); - } - } - intfHandle.firstInterfaceNumber = function.firstInterfaceNumber(); - interfaceHandles.add(intfHandle); - } - } - - @Override - public boolean isOpen() { - return showAsOpen; - } - - @Override - public synchronized void open() { - if (isOpen()) - throwException("device is already open"); - - showAsOpen = true; - } - - @Override - public synchronized void close() { - if (!isOpen()) - return; - - for (var intf : interfaceList) { - if (intf.isClaimed()) - releaseInterface(intf.number()); - } - - showAsOpen = false; - } - - public synchronized void claimInterface(int interfaceNumber) { - checkIsOpen(); - - var intfHandle = getInterfaceHandle(interfaceNumber); - if (intfHandle.interfaceHandle != null) - throwException("interface %d has already been claimed", interfaceNumber); - - var firstIntfHandle = intfHandle; - if (intfHandle.firstInterfaceNumber != interfaceNumber) - firstIntfHandle = getInterfaceHandle(intfHandle.firstInterfaceNumber); - - if (firstIntfHandle.devicePath == null) - throwException("interface number %d cannot be claimed (non WinUSB device?)", interfaceNumber); - - try (var arena = Arena.ofConfined()) { - - MemorySegment deviceHandle; - var errorState = allocateErrorState(arena); - - // open Windows device if needed - if (firstIntfHandle.deviceHandle == null) { - var pathSegment = Win.createSegmentFromString(firstIntfHandle.devicePath, arena); - deviceHandle = Kernel32B.CreateFileW(pathSegment, Kernel32.GENERIC_WRITE() | Kernel32.GENERIC_READ(), - Kernel32.FILE_SHARE_WRITE() | Kernel32.FILE_SHARE_READ(), NULL, Kernel32.OPEN_EXISTING(), - Kernel32.FILE_ATTRIBUTE_NORMAL() | Kernel32.FILE_FLAG_OVERLAPPED(), NULL, errorState); - - if (Win.isInvalidHandle(deviceHandle)) - throwLastError(errorState, "opening USB device %s failed", firstIntfHandle.devicePath); - - asyncTask.addDevice(deviceHandle); - - } else { - deviceHandle = firstIntfHandle.deviceHandle; - } - - try { - // open interface - var interfaceHandleHolder = arena.allocate(ADDRESS); - if (WinUSB2.WinUsb_Initialize(deviceHandle, interfaceHandleHolder, errorState) == 0) - throwLastError(errorState, "opening WinUSB device failed"); - var interfaceHandle = dereference(interfaceHandleHolder); - - firstIntfHandle.deviceHandle = deviceHandle; - firstIntfHandle.deviceOpenCount += 1; - intfHandle.interfaceHandle = interfaceHandle; - - } catch (Exception e) { - Kernel32.CloseHandle(deviceHandle); - throw e; - } - } - - setClaimed(interfaceNumber, true); - } - - @Override - public synchronized void selectAlternateSetting(int interfaceNumber, int alternateNumber) { - checkIsOpen(); - - var intfHandle = getInterfaceHandle(interfaceNumber); - if (intfHandle.interfaceHandle == null) - throwException("interface %d has not been claimed", interfaceNumber); - - var intf = getInterface(interfaceNumber); - - // check alternate setting - var altSetting = intf.getAlternate(alternateNumber); - if (altSetting == null) - throwException("interface %d does not have an alternate interface setting %d", interfaceNumber, - alternateNumber); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - if (WinUSB2.WinUsb_SetCurrentAlternateSetting(intfHandle.interfaceHandle, (byte) alternateNumber, - errorState) == 0) - throwLastError(errorState, "setting alternate interface failed"); - } - intf.setAlternate(altSetting); - } - - public synchronized void releaseInterface(int interfaceNumber) { - checkIsOpen(); - - var intfHandle = getInterfaceHandle(interfaceNumber); - if (intfHandle.interfaceHandle == null) - throwException("interface %d has not been claimed", interfaceNumber); - - var firstIntfHandle = intfHandle; - if (intfHandle.firstInterfaceNumber != interfaceNumber) - firstIntfHandle = getInterfaceHandle(intfHandle.firstInterfaceNumber); - - // close interface - WinUSB.WinUsb_Free(intfHandle.interfaceHandle); - intfHandle.interfaceHandle = null; - - // close device - firstIntfHandle.deviceOpenCount -= 1; - if (firstIntfHandle.deviceOpenCount == 0) { - Kernel32.CloseHandle(firstIntfHandle.deviceHandle); - firstIntfHandle.deviceHandle = null; - } - - setClaimed(interfaceNumber, false); - } - - @Override - public void controlTransferOut(USBControlTransfer setup, byte[] data) { - try (var arena = Arena.ofConfined()) { - - // copy data to native memory - var transfer = createSyncControlTransfer(); - var dataLength = data != null ? data.length : 0; - transfer.setDataSize(dataLength); - if (dataLength != 0) { - var buffer = arena.allocate(data.length); - buffer.copyFrom(MemorySegment.ofArray(data)); - transfer.setData(buffer); - } else { - transfer.setData(NULL); - } - - synchronized (transfer) { - submitControlTransfer(USBDirection.OUT, setup, transfer); - waitForTransfer(transfer, 0, USBDirection.OUT, 0); - } - } - } - - @Override - public byte[] controlTransferIn(USBControlTransfer setup, int length) { - try (var arena = Arena.ofConfined()) { - var transfer = createSyncControlTransfer(); - transfer.setData(arena.allocate(length)); - transfer.setDataSize(length); - - synchronized (transfer) { - submitControlTransfer(USBDirection.IN, setup, transfer); - waitForTransfer(transfer, 0, USBDirection.IN, 0); - } - - return transfer.data().asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); - } - } - - @Override - public void transferOut(int endpointNumber, byte[] data, int offset, int length, int timeout) { - try (var arena = Arena.ofConfined()) { - var buffer = arena.allocate(data.length); - buffer.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); - var transfer = createSyncTransfer(buffer); - - synchronized (transfer) { - submitTransferOut(endpointNumber, transfer); - waitForTransfer(transfer, timeout, USBDirection.OUT, endpointNumber); - } - } - } - - @Override - public byte[] transferIn(int endpointNumber, int timeout) { - var endpoint = getEndpoint(USBDirection.IN, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - - try (var arena = Arena.ofConfined()) { - var buffer = arena.allocate(endpoint.packetSize()); - var transfer = createSyncTransfer(buffer); - - synchronized (transfer) { - submitTransferIn(endpointNumber, transfer); - waitForTransfer(transfer, timeout, USBDirection.IN, endpointNumber); - } - - return buffer.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); - } - } - - private WindowsTransfer createSyncControlTransfer() { - var transfer = new WindowsTransfer(); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); - return transfer; - } - - private WindowsTransfer createSyncTransfer(MemorySegment data) { - var transfer = new WindowsTransfer(); - transfer.setData(data); - transfer.setDataSize((int) data.byteSize()); - transfer.setCompletion(USBDeviceImpl::onSyncTransferCompleted); - return transfer; - } - - @Override - protected Transfer createTransfer() { - return new WindowsTransfer(); - } - - @Override - protected void throwOSException(int errorCode, String message, Object... args) { - throwException(errorCode, message, args); - } - - synchronized void submitControlTransfer(USBDirection direction, USBControlTransfer setup, WindowsTransfer transfer) { - checkIsOpen(); - var intfHandle = findControlTransferInterface(setup); - - try (var arena = Arena.ofConfined()) { - var setupPacket = new SetupPacket(arena); - var bmRequest = - (direction == USBDirection.IN ? 0x80 : 0) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); - setupPacket.setRequestType(bmRequest); - setupPacket.setRequest(setup.request()); - setupPacket.setValue(setup.value()); - setupPacket.setIndex(setup.index()); - setupPacket.setLength(transfer.dataSize()); - - var errorState = allocateErrorState(arena); - asyncTask.prepareForSubmission(transfer); - - // submit transfer - if (WinUSB2.WinUsb_ControlTransfer(intfHandle.interfaceHandle, setupPacket.segment(), transfer.data(), - transfer.dataSize(), NULL, transfer.overlapped(), errorState) == 0) { - var err = Win.getLastError(errorState); - if (err != Kernel32.ERROR_IO_PENDING()) - throwException(err, "submitting control transfer failed"); - } - } - } - - synchronized void submitTransferOut(int endpointNumber, WindowsTransfer transfer) { - var endpoint = getEndpoint(USBDirection.OUT, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - asyncTask.prepareForSubmission(transfer); - - // submit transfer - if (WinUSB2.WinUsb_WritePipe(intfHandle.interfaceHandle, endpoint.endpointAddress(), transfer.data(), - transfer.dataSize(), NULL, transfer.overlapped(), errorState) == 0) { - var err = Win.getLastError(errorState); - if (err != Kernel32.ERROR_IO_PENDING()) - throwException(err, "submitting transfer OUT failed"); - } - } - } - - synchronized void submitTransferIn(int endpointNumber, WindowsTransfer transfer) { - var endpoint = getEndpoint(USBDirection.IN, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - asyncTask.prepareForSubmission(transfer); - - // submit transfer - if (WinUSB2.WinUsb_ReadPipe(intfHandle.interfaceHandle, endpoint.endpointAddress(), transfer.data(), - transfer.dataSize(), NULL, transfer.overlapped(), errorState) == 0) { - var err = Win.getLastError(errorState); - if (err != Kernel32.ERROR_IO_PENDING()) - throwException(err, "submitting transfer IN failed"); - } - } - } - - synchronized void configureForAsyncIo(USBDirection direction, int endpointNumber) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - - var timeoutHolder = arena.allocate(JAVA_INT, 0); - if (WinUSB2.WinUsb_SetPipePolicy(intfHandle.interfaceHandle, endpoint.endpointAddress(), - WinUSB.PIPE_TRANSFER_TIMEOUT(), (int) timeoutHolder.byteSize(), timeoutHolder, errorState) == 0) - throwLastError(errorState, "setting timeout failed"); - - var rawIoHolder = arena.allocate(JAVA_BYTE, (byte) 1); - if (WinUSB2.WinUsb_SetPipePolicy(intfHandle.interfaceHandle, endpoint.endpointAddress(), WinUSB.RAW_IO(), - (int) rawIoHolder.byteSize(), rawIoHolder, errorState) == 0) - throwLastError(errorState, "setting raw IO failed"); - } - } - - @Override - public synchronized void clearHalt(USBDirection direction, int endpointNumber) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - if (WinUSB2.WinUsb_ResetPipe(intfHandle.interfaceHandle, endpoint.endpointAddress(), errorState) == 0) - throwLastError(errorState, "clearing halt failed"); - } - } - - @Override - public synchronized void abortTransfers(USBDirection direction, int endpointNumber) { - var endpoint = getEndpoint(direction, endpointNumber, USBTransferType.BULK, USBTransferType.INTERRUPT); - var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); - - try (var arena = Arena.ofConfined()) { - var errorState = allocateErrorState(arena); - if (WinUSB2.WinUsb_AbortPipe(intfHandle.interfaceHandle, endpoint.endpointAddress(), errorState) == 0) - throwLastError(errorState, "aborting transfers on endpoint failed"); - } - } - - @Override - public synchronized InputStream openInputStream(int endpointNumber, int bufferSize) { - // check that endpoint number is valid - getEndpoint(USBDirection.IN, endpointNumber, USBTransferType.BULK, null); - - return new WindowsEndpointInputStream(this, endpointNumber, bufferSize); - } - - @Override - public synchronized OutputStream openOutputStream(int endpointNumber, int bufferSize) { - // check that endpoint number is valid - getEndpoint(USBDirection.OUT, endpointNumber, USBTransferType.BULK, null); - - return new WindowsEndpointOutputStream(this, endpointNumber, bufferSize); - } - - private InterfaceHandle getInterfaceHandle(int interfaceNumber) { - for (var intfHandle : interfaceHandles) { - if (intfHandle.interfaceNumber == interfaceNumber) - return intfHandle; - } - - throwException("invalid interface number %s", interfaceNumber); - throw new AssertionError("not reached"); - } - - private InterfaceHandle findControlTransferInterface(USBControlTransfer setup) { - - var interfaceNumber = -1; - int endpointNumber; - - if (setup.recipient() == USBRecipient.INTERFACE) { - - interfaceNumber = setup.index() & 0xff; - - } else if (setup.recipient() == USBRecipient.ENDPOINT) { - - endpointNumber = setup.index() & 0x7f; - var direction = (setup.index() & 0x80) != 0 ? USBDirection.IN : USBDirection.OUT; - if (endpointNumber != 0) { - interfaceNumber = getInterfaceNumber(direction, endpointNumber); - if (interfaceNumber == -1) - throwException("invalid endpoint number %d or interface not claimed", endpointNumber); - } - } - - if (interfaceNumber >= 0) { - var intfHandle = getInterfaceHandle(interfaceNumber); - if (intfHandle.interfaceHandle == null) - throwException("interface number %d has not been claimed", interfaceNumber); - return intfHandle; - } - - // for control transfer to device, use any claimed interface - for (var intfHandle : interfaceHandles) { - if (intfHandle.interfaceHandle != null) - return intfHandle; - } - - throwException("control transfer cannot be executed as no interface has been claimed"); - throw new AssertionError("not reached"); - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDeviceRegistry.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDeviceRegistry.java deleted file mode 100644 index e9f05e69..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDeviceRegistry.java +++ /dev/null @@ -1,450 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// - -package net.codecrete.usb.windows; - -import net.codecrete.usb.USBDevice; -import net.codecrete.usb.USBException; -import net.codecrete.usb.common.ScopeCleanup; -import net.codecrete.usb.common.USBDeviceImpl; -import net.codecrete.usb.common.USBDeviceRegistry; -import net.codecrete.usb.usbstandard.ConfigurationDescriptor; -import net.codecrete.usb.usbstandard.DeviceDescriptor; -import net.codecrete.usb.usbstandard.SetupPacket; -import net.codecrete.usb.usbstandard.StringDescriptor; -import net.codecrete.usb.windows.gen.kernel32.Kernel32; -import net.codecrete.usb.windows.gen.usbioctl.USBIoctl; -import net.codecrete.usb.windows.gen.usbioctl._USB_DESCRIPTOR_REQUEST; -import net.codecrete.usb.windows.gen.usbioctl._USB_NODE_CONNECTION_INFORMATION_EX; -import net.codecrete.usb.windows.gen.user32.*; -import net.codecrete.usb.windows.winsdk.Kernel32B; -import net.codecrete.usb.windows.winsdk.User32B; - -import java.lang.foreign.Arena; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.*; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static java.lang.System.Logger.Level.DEBUG; -import static java.lang.System.Logger.Level.INFO; -import static java.lang.foreign.MemorySegment.NULL; -import static java.lang.foreign.ValueLayout.*; -import static net.codecrete.usb.usbstandard.Constants.*; -import static net.codecrete.usb.windows.DevicePropertyKey.*; -import static net.codecrete.usb.windows.USBConstants.GUID_DEVINTERFACE_USB_DEVICE; -import static net.codecrete.usb.windows.USBConstants.GUID_DEVINTERFACE_USB_HUB; -import static net.codecrete.usb.windows.Win.allocateErrorState; -import static net.codecrete.usb.windows.WindowsUSBException.throwException; -import static net.codecrete.usb.windows.WindowsUSBException.throwLastError; - -/** - * Windows implementation of USB device registry. - *

- * To retrieve details of a USB device, this class accesses it indirectly - * via the parent. To address it the parent's handle (hub handle) and - * the device's port number is needed. - *

- */ -public class WindowsUSBDeviceRegistry extends USBDeviceRegistry { - - private static final System.Logger LOG = System.getLogger(WindowsUSBDeviceRegistry.class.getName()); - - private static final long REQUEST_DATA_OFFSET - = _USB_DESCRIPTOR_REQUEST.$LAYOUT().byteOffset(PathElement.groupElement("Data")); - - @Override - protected void monitorDevices() { - try (var arena = Arena.ofConfined()) { - - MemorySegment hwnd; - var errorState = allocateErrorState(arena); - - try { - final var className = Win.createSegmentFromString("USB_MONITOR", arena); - final var windowName = Win.createSegmentFromString("USB device monitor", arena); - final var instance = Kernel32.GetModuleHandleW(NULL); - - // create upcall for handling window messages - var handleWindowMessageMH = MethodHandles.lookup().findVirtual(WindowsUSBDeviceRegistry.class, - "handleWindowMessage", MethodType.methodType(long.class, MemorySegment.class, int.class, - long.class, long.class)).bindTo(this); - var handleWindowMessageStub = Linker.nativeLinker().upcallStub(handleWindowMessageMH, - FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_INT, JAVA_LONG, JAVA_LONG), arena); - - // register window class - var wx = tagWNDCLASSEXW.allocate(arena); - tagWNDCLASSEXW.cbSize$set(wx, (int) wx.byteSize()); - tagWNDCLASSEXW.lpfnWndProc$set(wx, handleWindowMessageStub); - tagWNDCLASSEXW.hInstance$set(wx, instance); - tagWNDCLASSEXW.lpszClassName$set(wx, className); - var atom = User32B.RegisterClassExW(wx, errorState); - if (atom == 0) - throwLastError(errorState, "internal error (RegisterClassExW)"); - - // create message-only window - hwnd = User32B.CreateWindowExW(0, className, windowName, 0, 0, 0, 0, 0, User32.HWND_MESSAGE(), NULL, - instance, NULL, errorState); - if (hwnd.address() == 0) - throwLastError(errorState, "internal error (CreateWindowExW)"); - - // configure notifications - var notificationFilter = _DEV_BROADCAST_DEVICEINTERFACE_W.allocate(arena); - _DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_size$set(notificationFilter, (int) notificationFilter.byteSize()); - _DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_devicetype$set(notificationFilter, - User32.DBT_DEVTYP_DEVICEINTERFACE()); - _DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_classguid$slice(notificationFilter).copyFrom(GUID_DEVINTERFACE_USB_DEVICE); - - var notifyHandle = User32B.RegisterDeviceNotificationW(hwnd, notificationFilter, - User32.DEVICE_NOTIFY_WINDOW_HANDLE(), errorState); - if (notifyHandle.address() == 0) - throwLastError(errorState, "internal error (RegisterDeviceNotificationW)"); - - // initial device enumeration - enumeratePresentDevices(); - - } catch (Exception e) { - enumerationFailed(e); - return; - } - - // process messages - var msg = tagMSG.allocate(arena); - int err; - //noinspection StatementWithEmptyBody - while ((err = User32B.GetMessageW(msg, hwnd, 0, 0, errorState)) > 0) - ; // do nothing - - if (err == -1) - throwLastError(errorState, "internal error (GetMessageW)"); - } - } - - @SuppressWarnings("java:S106") - private void enumeratePresentDevices() { - - List deviceList = new ArrayList<>(); - try (var cleanup = new ScopeCleanup(); - var deviceInfoSet = DeviceInfoSet.ofPresentDevices(GUID_DEVINTERFACE_USB_DEVICE, null)) { - - // ensure all hubs are closed later - final var hubHandles = new HashMap(); - cleanup.add(() -> hubHandles.forEach((path, handle) -> Kernel32.CloseHandle(handle))); - - // iterate all devices - while (deviceInfoSet.next()) { - - var instanceId = deviceInfoSet.getStringProperty(InstanceId); - var devicePath = DeviceInfoSet.getDevicePath(instanceId, GUID_DEVINTERFACE_USB_DEVICE); - - try { - deviceList.add(createDeviceFromDeviceInfo(deviceInfoSet, devicePath, hubHandles)); - - } catch (Exception e) { - LOG.log(INFO, String.format("failed to retrieve information about device %s - ignoring device", devicePath), e); - } - } - - setInitialDeviceList(deviceList); - } - } - - private USBDevice createDeviceFromDeviceInfo(DeviceInfoSet deviceInfoSet, String devicePath, - HashMap hubHandles) { - try (var arena = Arena.ofConfined()) { - - var usbPortNum = deviceInfoSet.getIntProperty(Address); - var parentInstanceId = deviceInfoSet.getStringProperty(Parent); - var hubPath = DeviceInfoSet.getDevicePath(parentInstanceId, GUID_DEVINTERFACE_USB_HUB); - - // open hub if not open yet - var hubHandle = hubHandles.get(hubPath); - if (hubHandle == null) { - var hubPathSeg = Win.createSegmentFromString(hubPath, arena); - var errorState = allocateErrorState(arena); - hubHandle = Kernel32B.CreateFileW(hubPathSeg, Kernel32.GENERIC_WRITE(), Kernel32.FILE_SHARE_WRITE(), - NULL, Kernel32.OPEN_EXISTING(), 0, NULL, errorState); - if (Win.isInvalidHandle(hubHandle)) - throwLastError(errorState, "internal error (opening hub device)"); - hubHandles.put(hubPath, hubHandle); - } - - // check for composite device - var children = getChildDevices(deviceInfoSet, devicePath); - - return createDevice(devicePath, children, hubHandle, usbPortNum); - } - } - - @SuppressWarnings({"java:S106", "java:S1168"}) - private Map getChildDevices(DeviceInfoSet deviceInfoSet, String devicePath) { - if (!deviceInfoSet.isCompositeDevice()) - return null; - - // For certain devices, it seems to take some time until the "Device_Children" - // entry is present. So we retry a few times if needed and pause in between. - List childrenInstanceIDs; - var numTries = 5; - while (true) { - numTries -= 1; - childrenInstanceIDs = deviceInfoSet.getStringListProperty(Children); - if (childrenInstanceIDs != null || numTries == 0) - break; - - // sleep and retry - try { - LOG.log(DEBUG, "Sleeping for 200ms (after unsuccessfully retrieving DEVPKEY_Device_Children)"); - //noinspection BusyWait - Thread.sleep(200); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - if (childrenInstanceIDs == null) { - LOG.log(DEBUG, "unable to retrieve information about children of device {0} - ignoring", devicePath); - return null; - } - - // create children map (interface number -> device path) - return childrenInstanceIDs.stream() - .map(WindowsUSBDeviceRegistry::getNumberPathTuple) - .filter(Objects::nonNull) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - /** - * Retrieve device descriptor and create {@code USBDevice} instance - * - * @param devicePath the device path - * @param children map of child device paths, indexed by the first interface number - * @param hubHandle the hub handle (parent) - * @param usbPortNum the USB port number - * @return the {@code USBDevice} instance - */ - private USBDevice createDevice(String devicePath, Map children, MemorySegment hubHandle, - int usbPortNum) { - - try (var arena = Arena.ofConfined()) { - - // get device descriptor - var connInfo = _USB_NODE_CONNECTION_INFORMATION_EX.allocate(arena); - _USB_NODE_CONNECTION_INFORMATION_EX.ConnectionIndex$set(connInfo, usbPortNum); - var sizeHolder = arena.allocate(JAVA_INT); - var errorState = allocateErrorState(arena); - if (Kernel32B.DeviceIoControl(hubHandle, USBIoctl.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX(), - connInfo, (int) connInfo.byteSize(), connInfo, (int) connInfo.byteSize(), sizeHolder, NULL, - errorState) == 0) - throwLastError(errorState, "internal error (getting device descriptor failed)"); - - var descriptorSegment = _USB_NODE_CONNECTION_INFORMATION_EX.DeviceDescriptor$slice(connInfo); - var deviceDescriptor = new DeviceDescriptor(descriptorSegment); - - var vendorId = deviceDescriptor.vendorID(); - var productId = deviceDescriptor.productID(); - - var configDesc = getDescriptor(hubHandle, usbPortNum, CONFIGURATION_DESCRIPTOR_TYPE, 0, (short) 0, arena); - - var device = new WindowsUSBDevice(devicePath, children, vendorId, productId, configDesc); - device.setFromDeviceDescriptor(descriptorSegment); - device.setProductString(descriptorSegment, index -> getStringDescriptor(hubHandle, usbPortNum, index)); - - return device; - } - } - - private MemorySegment getDescriptor(MemorySegment hubHandle, int usbPortNumber, int descriptorType, int index, - short languageID, Arena arena) { - return getDescriptor(hubHandle, usbPortNumber, descriptorType, index, languageID, 0, arena); - - } - - private MemorySegment getDescriptor(MemorySegment hubHandle, int usbPortNumber, int descriptorType, int index, - short languageID, int requestSize, Arena arena) { - var size = requestSize != 0 ? requestSize + (int) REQUEST_DATA_OFFSET : 256; - - // create descriptor requests - var descriptorRequest = arena.allocate(size); - _USB_DESCRIPTOR_REQUEST.ConnectionIndex$set(descriptorRequest, usbPortNumber); - var setupPacket = new SetupPacket(_USB_DESCRIPTOR_REQUEST.SetupPacket$slice(descriptorRequest)); - setupPacket.setRequestType(0x80); // device-to-host / type standard / recipient device - setupPacket.setRequest(USBConstants.USB_REQUEST_GET_DESCRIPTOR); - setupPacket.setValue((descriptorType << 8) | index); - setupPacket.setIndex(languageID); - setupPacket.setLength(size - (int) REQUEST_DATA_OFFSET); - - // execute request - var effectiveSizeHolder = arena.allocate(JAVA_INT); - var errorState = allocateErrorState(arena); - if (Kernel32B.DeviceIoControl(hubHandle, USBIoctl.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION(), - descriptorRequest, size, descriptorRequest, size, effectiveSizeHolder, NULL, errorState) == 0) - throwLastError(errorState, "internal error (retrieving descriptor %d failed)", index); - - // determine size of descriptor - int expectedSize; - if (descriptorType != CONFIGURATION_DESCRIPTOR_TYPE) { - expectedSize = 255 & descriptorRequest.get(JAVA_BYTE, REQUEST_DATA_OFFSET); - } else { - var configDesc = - new ConfigurationDescriptor(descriptorRequest.asSlice(REQUEST_DATA_OFFSET, ConfigurationDescriptor.LAYOUT.byteSize())); - expectedSize = configDesc.totalLength(); - } - - // check against effective size - var effectiveSize = effectiveSizeHolder.get(JAVA_INT, 0) - REQUEST_DATA_OFFSET; - if (effectiveSize != expectedSize) { - if (requestSize != 0) - throwException("internal error (unexpected descriptor size)"); - - // repeat with correct size - return getDescriptor(hubHandle, usbPortNumber, descriptorType, index, languageID, expectedSize, arena); - } - - return descriptorRequest.asSlice(REQUEST_DATA_OFFSET, effectiveSize); - } - - @SuppressWarnings("java:S106") - private String getStringDescriptor(MemorySegment hubHandle, int usbPortNumber, int index) { - if (index == 0) - return null; - - try (var arena = Arena.ofConfined()) { - var stringDesc = new StringDescriptor(getDescriptor(hubHandle, usbPortNumber, STRING_DESCRIPTOR_TYPE, - index, DEFAULT_LANGUAGE, arena)); - return stringDesc.string(); - - } catch (USBException e) { - return null; - } - } - - @SuppressWarnings("java:S1144") - private long handleWindowMessage(MemorySegment hWnd, int uMsg, long wParam, long lParam) { - - // check for message related to connecting/disconnecting devices - if (uMsg == User32.WM_DEVICECHANGE() && (wParam == User32.DBT_DEVICEARRIVAL() || wParam == User32.DBT_DEVICEREMOVECOMPLETE())) { - var data = MemorySegment.ofAddress(lParam).reinterpret(_DEV_BROADCAST_DEVICEINTERFACE_W.sizeof()); - if (_DEV_BROADCAST_HDR.dbch_devicetype$get(data) == User32.DBT_DEVTYP_DEVICEINTERFACE()) { - - // get device path - var nameSlice = - MemorySegment.ofAddress(_DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_name$slice(data).address()).reinterpret(500); - var devicePath = Win.createStringFromSegment(nameSlice); - if (wParam == User32.DBT_DEVICEARRIVAL()) - onDeviceConnected(devicePath); - else - onDeviceDisconnected(devicePath); - return 0; - } - } - - // default message handling - return User32.DefWindowProcW(hWnd, uMsg, wParam, lParam); - } - - @SuppressWarnings("java:S106") - private void onDeviceConnected(String devicePath) { - try (var cleanup = new ScopeCleanup(); - var deviceInfoSet = DeviceInfoSet.ofPath(devicePath)) { - - // ensure all hubs are closed later - final var hubHandles = new HashMap(); - cleanup.add(() -> hubHandles.forEach((path, handle) -> Kernel32.CloseHandle(handle))); - - try { - // create device instance - var device = createDeviceFromDeviceInfo(deviceInfoSet, devicePath, hubHandles); - - // add it to device list - addDevice(device); - - } catch (Exception e) { - LOG.log(INFO, String.format("failed to retrieve information about device %s - ignoring device", devicePath), e); - } - } - } - - private void onDeviceDisconnected(String devicePath) { - closeAndRemoveDevice(devicePath); - } - - /** - * Finds the index of the device in the list. - *

- * This override uses a case-insensitive string comparison as Windows uses different casing - * when initially enumerating devices and during later monitoring. - *

- * - * @param deviceList the device list - * @param deviceId the unique device ID - * @return index, or -1 if not found - */ - @Override - protected int findDeviceIndex(List deviceList, Object deviceId) { - var id = deviceId.toString(); - for (var i = 0; i < deviceList.size(); i++) { - var dev = (USBDeviceImpl) deviceList.get(i); - if (id.equalsIgnoreCase(dev.getUniqueId().toString())) - return i; - } - return -1; - } - - /** - * Looks up the interface number and device path for the child device with the given instance ID. - * - * @param instanceId child instance ID - * @return tuple consisting of interface number and device path, or {@code null} if unsuccessful - */ - private static Map.Entry getNumberPathTuple(String instanceId) { - try (var deviceInfoSet = DeviceInfoSet.ofInstance(instanceId)) { - - // get hardware IDs (to extract interface number) - var hardwareIds = deviceInfoSet.getStringListProperty(HardwareIds); - if (hardwareIds == null) - throwException("internal error (device property 'HardwareIds' is missing)"); - var interfaceNumber = extractInterfaceNumber(hardwareIds); - if (interfaceNumber == -1) { - LOG.log(DEBUG, "Child device {0} has no interface number", instanceId); - return null; - } - - var devicePath = deviceInfoSet.getDevicePathByGUID(instanceId); - if (devicePath == null) { - LOG.log(DEBUG, "Child device {0} has no device path", instanceId); - return null; - } - - return new AbstractMap.SimpleImmutableEntry<>(interfaceNumber, devicePath); - } - } - - private static final Pattern MULTIPLE_INTERFACE_ID = Pattern.compile( - "USB\\\\VID_[0-9A-Fa-f]{4}&PID_[0-9A-Fa-f]{4}&MI_([0-9A-Fa-f]{2})"); - - private static int extractInterfaceNumber(List hardwareIds) { - // Also see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices - - for (var id : hardwareIds) { - var matcher = MULTIPLE_INTERFACE_ID.matcher(id); - if (matcher.find()) { - var intfHexNumber = matcher.group(1); - try { - return Integer.parseInt(intfHexNumber, 16); - } catch (NumberFormatException e) { - // ignore and try next one - } - } - } - - return -1; - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDevice.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDevice.java new file mode 100644 index 00000000..b98839c2 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDevice.java @@ -0,0 +1,669 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.windows; + +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbRecipient; +import net.codecrete.usb.UsbTransferType; +import net.codecrete.usb.common.Transfer; +import net.codecrete.usb.common.UsbDeviceImpl; +import net.codecrete.usb.usbstandard.SetupPacket; +import org.jetbrains.annotations.NotNull; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import static java.lang.System.Logger.Level.DEBUG; +import static java.lang.System.Logger.Level.INFO; +import static java.lang.foreign.MemorySegment.NULL; +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.nio.charset.StandardCharsets.UTF_16LE; +import static net.codecrete.usb.common.ForeignMemory.dereference; +import static net.codecrete.usb.windows.CustomApis.CloseHandle; +import static net.codecrete.usb.windows.CustomApis.WinUsb_ControlTransfer; +import static net.codecrete.usb.windows.Win.allocateErrorState; +import static net.codecrete.usb.windows.WindowsUsbException.throwException; +import static net.codecrete.usb.windows.WindowsUsbException.throwLastError; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_Children; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_HardwareIds; +import static windows.win32.devices.usb.Apis.WinUsb_AbortPipe; +import static windows.win32.devices.usb.Apis.WinUsb_Free; +import static windows.win32.devices.usb.Apis.WinUsb_GetAssociatedInterface; +import static windows.win32.devices.usb.Apis.WinUsb_Initialize; +import static windows.win32.devices.usb.Apis.WinUsb_ReadPipe; +import static windows.win32.devices.usb.Apis.WinUsb_ResetPipe; +import static windows.win32.devices.usb.Apis.WinUsb_SetCurrentAlternateSetting; +import static windows.win32.devices.usb.Apis.WinUsb_SetPipePolicy; +import static windows.win32.devices.usb.Apis.WinUsb_WritePipe; +import static windows.win32.devices.usb.WINUSB_PIPE_POLICY.PIPE_TRANSFER_TIMEOUT; +import static windows.win32.devices.usb.WINUSB_PIPE_POLICY.RAW_IO; +import static windows.win32.foundation.GENERIC_ACCESS_RIGHTS.GENERIC_READ; +import static windows.win32.foundation.GENERIC_ACCESS_RIGHTS.GENERIC_WRITE; +import static windows.win32.foundation.WIN32_ERROR.ERROR_INVALID_PARAMETER; +import static windows.win32.foundation.WIN32_ERROR.ERROR_IO_PENDING; +import static windows.win32.storage.filesystem.Apis.CreateFileW; +import static windows.win32.storage.filesystem.FILE_CREATION_DISPOSITION.OPEN_EXISTING; +import static windows.win32.storage.filesystem.FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL; +import static windows.win32.storage.filesystem.FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED; +import static windows.win32.storage.filesystem.FILE_SHARE_MODE.FILE_SHARE_READ; +import static windows.win32.storage.filesystem.FILE_SHARE_MODE.FILE_SHARE_WRITE; + +/** + * Windows implementation for USB device. + */ +@SuppressWarnings("java:S2160") +public class WindowsUsbDevice extends UsbDeviceImpl { + + private static final System.Logger LOG = System.getLogger(WindowsUsbDevice.class.getName()); + + private final WindowsAsyncTask asyncTask; + /** + * Indicates if the device is a composite device + */ + private final boolean isComposite; + + private List interfaceHandles; + + // device paths by interface number (first interface of function) + private Map devicePaths; + + /** + * Indicates if {@link #open()} has been called. Since separate interfaces can have separate underlying + * Windows device, {@link #claimInterface(int)} instead of {@link #open()} will open the Windows device. + * (volatile: written under the device monitor, read unlocked via {@link #isOpened()}) + */ + private volatile boolean showAsOpen; + + WindowsUsbDevice(String devicePath, int vendorId, int productId, MemorySegment configDesc, boolean isComposite) { + super(devicePath, vendorId, productId); + asyncTask = WindowsAsyncTask.INSTANCE; + this.isComposite = isComposite; + if (isComposite) + devicePaths = new HashMap<>(); + readDescription(configDesc); + } + + private void readDescription(MemorySegment configDesc) { + var configuration = setConfigurationDescriptor(configDesc); + + // build list of interface handles + interfaceHandles = configuration.interfaces().stream() + .map(intf -> { + var interfaceNumber = intf.getNumber(); + var function = configuration.findFunction(interfaceNumber); + return new InterfaceHandle(interfaceNumber, function.firstInterfaceNumber()); + }). + toList(); + } + + @Override + public boolean isOpened() { + return showAsOpen; + } + + @Override + public synchronized void open() { + checkIsClosed("device is already open"); + showAsOpen = true; + } + + @Override + public synchronized void close() { + if (!isOpened()) + return; + + for (var intf : interfaceList) { + if (intf.isClaimed()) + releaseInterface(intf.getNumber()); + } + + showAsOpen = false; + } + + public void claimInterface(int interfaceNumber) { + // When a device is plugged in, a notification is sent. For composite devices, it is a notification + // that the composite device is ready. Each composite function will be registered separately and + // the related information will be available with a delay. So for composite functions, several + // retries might be needed until the device path is available. + var numRetries = 30; // 30 x 100ms + // Defer interruption: keep a local flag instead of re-asserting the interrupt + // (which would make the remaining backoff sleeps throw immediately and defeat + // the retry delay). Re-assert when leaving the method. + var wasInterrupted = false; + try { + while (true) { + if (claimInterfaceSynchronized(interfaceNumber)) + return; // success + + numRetries -= 1; + if (numRetries == 0) + throw new UsbException("claiming interface failed (function has no device path / interface GUID, might be missing WinUSB driver)"); + + // sleep and retry + try { + LOG.log(DEBUG, "Sleeping for 100ms..."); + //noinspection BusyWait + Thread.sleep(100); + } catch (InterruptedException _) { + wasInterrupted = true; + } + } + } finally { + if (wasInterrupted) + Thread.currentThread().interrupt(); + } + } + + @SuppressWarnings("java:S3776") + private synchronized boolean claimInterfaceSynchronized(int interfaceNumber) { + checkIsOpen(); + + getInterfaceWithCheck(interfaceNumber, false); + + var intfHandle = getInterfaceHandle(interfaceNumber); + var firstIntfHandle = intfHandle; + if (intfHandle.firstInterfaceNumber != interfaceNumber) + firstIntfHandle = getInterfaceHandle(intfHandle.firstInterfaceNumber); + + var deviceOpenedHere = false; + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + + // both the device and the first interface must be opened for any interface belonging to the same function + if (firstIntfHandle.deviceHandle == null) { + var devicePath = getInterfaceDevicePath(firstIntfHandle.interfaceNumber); + if (devicePath == null) + return false; // retry later + + LOG.log(DEBUG, "opening device {0}", devicePath); + + // open Windows device if needed + var pathSegment = arena.allocateFrom(devicePath, UTF_16LE); + var deviceHandle = CreateFileW(errorState, pathSegment, GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + + if (Win.isInvalidHandle(deviceHandle)) + throwLastError(errorState, "claiming interface failed (opening USB device %s failed)", devicePath); + + MemorySegment interfaceHandle = null; + try { + // open first interface + var interfaceHandleHolder = arena.allocate(ADDRESS); + if (WinUsb_Initialize(errorState, deviceHandle, interfaceHandleHolder) == 0) { + if (Win.getLastError(errorState) == ERROR_INVALID_PARAMETER) + throw new UsbException( + "claiming interface failed (required WinUSB driver is probably not installed for the device)", + ERROR_INVALID_PARAMETER + ); + throwLastError(errorState, "claiming interface failed"); + } + interfaceHandle = dereference(interfaceHandleHolder); + + asyncTask.addDevice(deviceHandle); + + // Assign handles only after all fallible operations have succeeded. + // Otherwise a later claim would see them and submit I/O on a closed handle. + firstIntfHandle.deviceHandle = deviceHandle; + firstIntfHandle.winusbHandle = interfaceHandle; + deviceOpenedHere = true; + + } catch (Exception e) { + if (interfaceHandle != null) + WinUsb_Free(interfaceHandle); + CloseHandle(deviceHandle); + throw e; + } + } + + if (intfHandle != firstIntfHandle) { + try { + // open associated interface + var interfaceHandleHolder = arena.allocate(ADDRESS); + if (WinUsb_GetAssociatedInterface(errorState, firstIntfHandle.winusbHandle, + (byte) (intfHandle.interfaceNumber - firstIntfHandle.interfaceNumber - 1), + interfaceHandleHolder) == 0) + throwLastError(errorState, "claiming (associated) interface failed"); + intfHandle.winusbHandle = dereference(interfaceHandleHolder); + + } catch (Exception e) { + if (deviceOpenedHere) { + // no interface has been claimed yet, so close() would never release the device + WinUsb_Free(firstIntfHandle.winusbHandle); + CloseHandle(firstIntfHandle.deviceHandle); + firstIntfHandle.winusbHandle = null; + firstIntfHandle.deviceHandle = null; + } + throw e; + } + } + } + + firstIntfHandle.deviceOpenCount += 1; + setClaimed(interfaceNumber, true); + return true; + } + + @Override + public synchronized void selectAlternateSetting(int interfaceNumber, int alternateNumber) { + checkIsOpen(); + + var intf = getInterfaceWithCheck(interfaceNumber, true); + var intfHandle = getInterfaceHandle(interfaceNumber); + + // check alternate setting + var altSetting = intf.getAlternate(alternateNumber); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + if (WinUsb_SetCurrentAlternateSetting(errorState, intfHandle.winusbHandle, (byte) alternateNumber) == 0) + throwLastError(errorState, "setting alternate interface failed"); + } + intf.setAlternate(altSetting); + } + + public synchronized void releaseInterface(int interfaceNumber) { + checkIsOpen(); + + getInterfaceWithCheck(interfaceNumber, true); + + var intfHandle = getInterfaceHandle(interfaceNumber); + var firstIntfHandle = intfHandle; + if (intfHandle.firstInterfaceNumber != interfaceNumber) + firstIntfHandle = getInterfaceHandle(intfHandle.firstInterfaceNumber); + + setClaimed(interfaceNumber, false); + + if (intfHandle != firstIntfHandle) { + // close associated interface + WinUsb_Free(intfHandle.winusbHandle); + intfHandle.winusbHandle = null; + } + + // close device if needed + firstIntfHandle.deviceOpenCount -= 1; + if (firstIntfHandle.deviceOpenCount == 0) { + WinUsb_Free(firstIntfHandle.winusbHandle); + firstIntfHandle.winusbHandle = null; + + LOG.log(DEBUG, "closing device {0}", getCachedInterfaceDevicePath(interfaceNumber)); + + CloseHandle(firstIntfHandle.deviceHandle); + firstIntfHandle.deviceHandle = null; + } + } + + @Override + public void controlTransferOut(@NotNull UsbControlTransfer setup, byte[] data) { + try (var arena = Arena.ofConfined()) { + + // copy data to native memory + var transfer = createSyncControlTransfer(); + var dataLength = data != null ? data.length : 0; + transfer.setDataSize(dataLength); + if (dataLength != 0) { + var buffer = arena.allocate(data.length); + buffer.copyFrom(MemorySegment.ofArray(data)); + transfer.setData(buffer); + } else { + transfer.setData(NULL); + } + + synchronized (transfer) { + submitControlTransfer(UsbDirection.OUT, setup, transfer); + waitForTransfer(transfer, 0, UsbDirection.OUT, 0); + } + } + } + + @Override + public byte @NotNull [] controlTransferIn(@NotNull UsbControlTransfer setup, int length) { + try (var arena = Arena.ofConfined()) { + var transfer = createSyncControlTransfer(); + transfer.setData(arena.allocate(length)); + transfer.setDataSize(length); + + synchronized (transfer) { + submitControlTransfer(UsbDirection.IN, setup, transfer); + waitForTransfer(transfer, 0, UsbDirection.IN, 0); + } + + return transfer.data().asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); + } + } + + @Override + public void transferOut(int endpointNumber, byte @NotNull [] data, int offset, int length, int timeout) { + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var buffer = arena.allocate(data.length); + buffer.copyFrom(MemorySegment.ofArray(data).asSlice(offset, length)); + var transfer = createSyncTransfer(buffer); + + synchronized (transfer) { + submitTransferOut(endpointNumber, transfer); + waitForTransfer(transfer, timeout, UsbDirection.OUT, endpointNumber); + } + } + + @Override + public byte @NotNull [] transferIn(int endpointNumber, int timeout) { + var endpoint = getEndpoint(UsbDirection.IN, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + + // Auto arena: a transfer that times out may be abandoned (see UsbDeviceImpl.waitForTransfer), + // so the buffer must outlive a possible late completion instead of being freed deterministically. + var arena = Arena.ofAuto(); + var buffer = arena.allocate(endpoint.packetSize()); + var transfer = createSyncTransfer(buffer); + + synchronized (transfer) { + submitTransferIn(endpointNumber, transfer); + waitForTransfer(transfer, timeout, UsbDirection.IN, endpointNumber); + } + + return buffer.asSlice(0, transfer.resultSize()).toArray(JAVA_BYTE); + } + + private WindowsTransfer createSyncControlTransfer() { + var transfer = new WindowsTransfer(); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); + return transfer; + } + + private WindowsTransfer createSyncTransfer(MemorySegment data) { + var transfer = new WindowsTransfer(); + transfer.setData(data); + transfer.setDataSize((int) data.byteSize()); + transfer.setCompletion(UsbDeviceImpl::onSyncTransferCompleted); + return transfer; + } + + @Override + protected Transfer createTransfer() { + return new WindowsTransfer(); + } + + @Override + protected void throwOSException(int errorCode, String message, Object... args) { + throwException(errorCode, message, args); + } + + synchronized void submitControlTransfer(UsbDirection direction, UsbControlTransfer setup, WindowsTransfer transfer) { + checkIsOpen(); + var intfHandle = findControlTransferInterface(setup); + + try (var arena = Arena.ofConfined()) { + var setupPacket = new SetupPacket(arena); + var bmRequest = + (direction == UsbDirection.IN ? 0x80 : 0) | (setup.requestType().ordinal() << 5) | setup.recipient().ordinal(); + setupPacket.setRequestType(bmRequest); + setupPacket.setRequest(setup.request()); + setupPacket.setValue(setup.value()); + setupPacket.setIndex(setup.index()); + setupPacket.setLength(transfer.dataSize()); + + var errorState = allocateErrorState(arena); + asyncTask.prepareForSubmission(transfer); + + // submit transfer + if (WinUsb_ControlTransfer(errorState, intfHandle.winusbHandle, setupPacket.segment(), transfer.data(), + transfer.dataSize(), NULL, transfer.overlapped()) == 0) { + var err = Win.getLastError(errorState); + if (err != ERROR_IO_PENDING) { + asyncTask.submissionFailed(transfer); + throwException(err, "submitting control transfer failed"); + } + } + } + } + + synchronized void submitTransferOut(int endpointNumber, WindowsTransfer transfer) { + var endpoint = getEndpoint(UsbDirection.OUT, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + asyncTask.prepareForSubmission(transfer); + + // submit transfer + if (WinUsb_WritePipe(errorState, intfHandle.winusbHandle, endpoint.endpointAddress(), transfer.data(), + transfer.dataSize(), NULL, transfer.overlapped()) == 0) { + var err = Win.getLastError(errorState); + if (err != ERROR_IO_PENDING) { + asyncTask.submissionFailed(transfer); + throwException(err, "submitting transfer OUT failed"); + } + } + } + } + + synchronized void submitTransferIn(int endpointNumber, WindowsTransfer transfer) { + var endpoint = getEndpoint(UsbDirection.IN, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + asyncTask.prepareForSubmission(transfer); + + // submit transfer + if (WinUsb_ReadPipe(errorState, intfHandle.winusbHandle, endpoint.endpointAddress(), transfer.data(), + transfer.dataSize(), NULL, transfer.overlapped()) == 0) { + var err = Win.getLastError(errorState); + if (err != ERROR_IO_PENDING) { + asyncTask.submissionFailed(transfer); + throwException(err, "submitting transfer IN failed"); + } + } + } + } + + synchronized void configureForAsyncIo(UsbDirection direction, int endpointNumber) { + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + + var timeoutHolder = arena.allocate(JAVA_INT); + if (WinUsb_SetPipePolicy(errorState, intfHandle.winusbHandle, endpoint.endpointAddress(), + PIPE_TRANSFER_TIMEOUT, (int) timeoutHolder.byteSize(), timeoutHolder) == 0) + throwLastError(errorState, "setting timeout failed"); + + var rawIoHolder = arena.allocate(JAVA_BYTE); + rawIoHolder.setAtIndex(JAVA_BYTE, 0, (byte) 1); + if (WinUsb_SetPipePolicy(errorState, intfHandle.winusbHandle, endpoint.endpointAddress(), RAW_IO, + (int) rawIoHolder.byteSize(), rawIoHolder) == 0) + throwLastError(errorState, "setting raw IO failed"); + } + } + + @Override + public synchronized void clearHalt(UsbDirection direction, int endpointNumber) { + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + if (WinUsb_ResetPipe(errorState, intfHandle.winusbHandle, endpoint.endpointAddress()) == 0) + throwLastError(errorState, "clearing halt failed"); + } + } + + @Override + public synchronized void abortTransfers(UsbDirection direction, int endpointNumber) { + var endpoint = getEndpoint(direction, endpointNumber, UsbTransferType.BULK, UsbTransferType.INTERRUPT); + var intfHandle = getInterfaceHandle(endpoint.interfaceNumber()); + + try (var arena = Arena.ofConfined()) { + var errorState = allocateErrorState(arena); + if (WinUsb_AbortPipe(errorState, intfHandle.winusbHandle, endpoint.endpointAddress()) == 0) + throwLastError(errorState, "aborting transfers on endpoint failed"); + } + } + + @Override + public synchronized @NotNull InputStream openInputStream(int endpointNumber, int bufferSize) { + // check that endpoint number is valid + getEndpoint(UsbDirection.IN, endpointNumber, UsbTransferType.BULK, null); + + return new WindowsEndpointInputStream(this, endpointNumber, bufferSize); + } + + @Override + public synchronized @NotNull OutputStream openOutputStream(int endpointNumber, int bufferSize) { + // check that endpoint number is valid + getEndpoint(UsbDirection.OUT, endpointNumber, UsbTransferType.BULK, null); + + return new WindowsEndpointOutputStream(this, endpointNumber, bufferSize); + } + + private InterfaceHandle getInterfaceHandle(int interfaceNumber) { + for (var intfHandle : interfaceHandles) { + if (intfHandle.interfaceNumber == interfaceNumber) + return intfHandle; + } + + throwException("invalid interface number %s", interfaceNumber); + throw new AssertionError("not reached"); + } + + private InterfaceHandle findControlTransferInterface(UsbControlTransfer setup) { + + var interfaceNumber = -1; + int endpointNumber; + + if (setup.recipient() == UsbRecipient.INTERFACE) { + + interfaceNumber = setup.index() & 0xff; + + } else if (setup.recipient() == UsbRecipient.ENDPOINT) { + + endpointNumber = setup.index() & 0x7f; + var direction = (setup.index() & 0x80) != 0 ? UsbDirection.IN : UsbDirection.OUT; + if (endpointNumber != 0) { + interfaceNumber = getInterfaceNumber(direction, endpointNumber); + if (interfaceNumber == -1) + throwException("invalid endpoint number %d or interface not claimed", endpointNumber); + } + } + + if (interfaceNumber >= 0) { + var intfHandle = getInterfaceHandle(interfaceNumber); + if (intfHandle.winusbHandle == null) + throwException("interface number %d has not been claimed", interfaceNumber); + return intfHandle; + } + + // for control transfer to device, use any claimed interface + for (var intfHandle : interfaceHandles) { + if (intfHandle.winusbHandle != null) + return intfHandle; + } + + throwException("control transfer cannot be executed as no interface has been claimed"); + throw new AssertionError("not reached"); + } + + private String getInterfaceDevicePath(int interfaceNumber) { + var devicePath = getCachedInterfaceDevicePath(interfaceNumber); + if (devicePath != null) + return devicePath; + + var parentDevicePath = (String) getUniqueId(); + + try (var deviceInfoSet = DeviceInfoSet.ofPath(parentDevicePath)) { + var childrenInstanceIDs = deviceInfoSet.getStringListProperty(DEVPKEY_Device_Children()); + if (childrenInstanceIDs == null) { + LOG.log(DEBUG, "missing children instance IDs for device {0}", parentDevicePath); + return null; + + } else { + LOG.log(DEBUG, "children instance IDs: {0}", childrenInstanceIDs); + + for (var instanceId : childrenInstanceIDs) { + devicePath = getChildDevicePath(instanceId, interfaceNumber); + if (devicePath != null) + return devicePath; + } + } + } + + return null; // retry later + } + + private String getCachedInterfaceDevicePath(int interfaceNumber) { + if (!isComposite) + return (String) getUniqueId(); + return devicePaths.get(interfaceNumber); + } + + private String getChildDevicePath(String instanceId, int interfaceNumber) { + try (var deviceInfoSet = DeviceInfoSet.ofInstance(instanceId)) { + + // get hardware IDs (to extract interface number) + var hardwareIds = deviceInfoSet.getStringListProperty(DEVPKEY_Device_HardwareIds()); + if (hardwareIds == null) { + LOG.log(DEBUG, "child device {0} has no hardware IDs", instanceId); + return null; + } + + var extractedNumber = extractInterfaceNumber(hardwareIds); + if (extractedNumber == -1) { + LOG.log(DEBUG, "child device {0} has no interface number", instanceId); + return null; + } + + if (extractedNumber != interfaceNumber) + return null; + + var devicePath = deviceInfoSet.getDevicePathByGUID(instanceId); + if (devicePath == null) { + LOG.log(INFO, "Child device {0} has no device path / interface GUID", instanceId); + throw new UsbException("claiming interface failed (composite function has no device path / interface GUID; the required WinUSB driver is probably not installed)"); + } + + if (devicePaths == null) + devicePaths = new HashMap<>(); + devicePaths.put(interfaceNumber, devicePath); + return devicePath; + } + } + + private static final Pattern MULTIPLE_INTERFACE_ID = Pattern.compile( + "USB\\\\VID_[0-9A-Fa-f]{4}&PID_[0-9A-Fa-f]{4}&MI_([0-9A-Fa-f]{2})"); + + private static int extractInterfaceNumber(List hardwareIds) { + // Also see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices + + for (var id : hardwareIds) { + var matcher = MULTIPLE_INTERFACE_ID.matcher(id); + if (matcher.find()) { + var intfHexNumber = matcher.group(1); + try { + return Integer.parseInt(intfHexNumber, 16); + } catch (NumberFormatException _) { + // ignore and try next one + } + } + } + + return -1; + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDeviceRegistry.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDeviceRegistry.java new file mode 100644 index 00000000..d9f86393 --- /dev/null +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbDeviceRegistry.java @@ -0,0 +1,396 @@ +// +// Java Does USB +// Copyright (c) 2022 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.windows; + +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.common.ScopeCleanup; +import net.codecrete.usb.common.UsbDeviceImpl; +import net.codecrete.usb.common.UsbDeviceRegistry; +import net.codecrete.usb.usbstandard.ConfigurationDescriptor; +import net.codecrete.usb.usbstandard.DeviceDescriptor; +import net.codecrete.usb.usbstandard.SetupPacket; +import net.codecrete.usb.usbstandard.StringDescriptor; +import windows.win32.devices.usb.USB_DESCRIPTOR_REQUEST; +import windows.win32.devices.usb.USB_NODE_CONNECTION_INFORMATION_EX; +import windows.win32.ui.windowsandmessaging.DEV_BROADCAST_DEVICEINTERFACE_W; +import windows.win32.ui.windowsandmessaging.DEV_BROADCAST_HDR; +import windows.win32.ui.windowsandmessaging.MSG; +import windows.win32.ui.windowsandmessaging.WNDCLASSEXW; +import windows.win32.ui.windowsandmessaging.WNDPROC; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.lang.System.Logger.Level.INFO; +import static java.lang.foreign.MemorySegment.NULL; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static java.lang.foreign.ValueLayout.PathElement; +import static java.nio.charset.StandardCharsets.UTF_16LE; +import static net.codecrete.usb.usbstandard.Constants.CONFIGURATION_DESCRIPTOR_TYPE; +import static net.codecrete.usb.usbstandard.Constants.DEFAULT_LANGUAGE; +import static net.codecrete.usb.usbstandard.Constants.STRING_DESCRIPTOR_TYPE; +import static net.codecrete.usb.windows.CustomApis.CloseHandle; +import static net.codecrete.usb.windows.Win.allocateErrorState; +import static net.codecrete.usb.windows.WindowsUsbException.throwException; +import static net.codecrete.usb.windows.WindowsUsbException.throwLastError; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_Address; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_InstanceId; +import static windows.win32.devices.properties.Constants.DEVPKEY_Device_Parent; +import static windows.win32.devices.usb.Constants.GUID_DEVINTERFACE_USB_DEVICE; +import static windows.win32.devices.usb.Constants.GUID_DEVINTERFACE_USB_HUB; +import static windows.win32.devices.usb.Constants.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION; +import static windows.win32.devices.usb.Constants.IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX; +import static windows.win32.devices.usb.Constants.USB_REQUEST_GET_DESCRIPTOR; +import static windows.win32.foundation.GENERIC_ACCESS_RIGHTS.GENERIC_WRITE; +import static windows.win32.storage.filesystem.Apis.CreateFileW; +import static windows.win32.storage.filesystem.FILE_CREATION_DISPOSITION.OPEN_EXISTING; +import static windows.win32.storage.filesystem.FILE_SHARE_MODE.FILE_SHARE_WRITE; +import static windows.win32.system.io.Apis.DeviceIoControl; +import static windows.win32.system.libraryloader.Apis.GetModuleHandleW; +import static windows.win32.ui.windowsandmessaging.Apis.CreateWindowExW; +import static windows.win32.ui.windowsandmessaging.Apis.DefWindowProcW; +import static windows.win32.ui.windowsandmessaging.Apis.GetMessageW; +import static windows.win32.ui.windowsandmessaging.Apis.RegisterClassExW; +import static windows.win32.ui.windowsandmessaging.Apis.RegisterDeviceNotificationW; +import static windows.win32.ui.windowsandmessaging.Constants.DBT_DEVICEARRIVAL; +import static windows.win32.ui.windowsandmessaging.Constants.DBT_DEVICEREMOVECOMPLETE; +import static windows.win32.ui.windowsandmessaging.Constants.HWND_MESSAGE; +import static windows.win32.ui.windowsandmessaging.Constants.WM_DEVICECHANGE; +import static windows.win32.ui.windowsandmessaging.DEV_BROADCAST_HDR_DEVICE_TYPE.DBT_DEVTYP_DEVICEINTERFACE; +import static windows.win32.ui.windowsandmessaging.REGISTER_NOTIFICATION_FLAGS.DEVICE_NOTIFY_WINDOW_HANDLE; + +/** + * Windows implementation of USB device registry. + *

+ * To retrieve details of a USB device, this class accesses it indirectly + * via the parent. To address it the parent's handle (hub handle) and + * the device's port number is needed. + *

+ */ +public class WindowsUsbDeviceRegistry extends UsbDeviceRegistry { + + private static final System.Logger LOG = System.getLogger(WindowsUsbDeviceRegistry.class.getName()); + + private static final long REQUEST_DATA_OFFSET + = USB_DESCRIPTOR_REQUEST.layout().byteOffset(PathElement.groupElement("Data")); + + @Override + protected void monitorDevices() { + try (var arena = Arena.ofConfined()) { + + MemorySegment hwnd; + var errorState = allocateErrorState(arena); + + try { + final var className = arena.allocateFrom("USB_MONITOR", UTF_16LE); + final var windowName = arena.allocateFrom("USB device monitor", UTF_16LE); + final var instance = GetModuleHandleW(errorState, NULL); + + // register window class + var wx = WNDCLASSEXW.allocate(arena); + WNDCLASSEXW.lpfnWndProc(wx, WNDPROC.allocate(arena, this::handleWindowMessage)); + WNDCLASSEXW.hInstance(wx, instance); + WNDCLASSEXW.lpszClassName(wx, className); + var atom = RegisterClassExW(errorState, wx); + if (atom == 0) + throwLastError(errorState, "internal error (RegisterClassExW)"); + + // create message-only window + hwnd = CreateWindowExW(errorState, 0, className, windowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, + instance, NULL); + if (hwnd.address() == 0) + throwLastError(errorState, "internal error (CreateWindowExW)"); + + // configure notifications + var notificationFilter = DEV_BROADCAST_DEVICEINTERFACE_W.allocate(arena, 260); + DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_size(notificationFilter, (int) notificationFilter.byteSize()); + DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_devicetype(notificationFilter, DBT_DEVTYP_DEVICEINTERFACE); + DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_classguid(notificationFilter).copyFrom(GUID_DEVINTERFACE_USB_DEVICE()); + + var notifyHandle = RegisterDeviceNotificationW(errorState, hwnd, notificationFilter, + DEVICE_NOTIFY_WINDOW_HANDLE); + if (notifyHandle.address() == 0) + throwLastError(errorState, "internal error (RegisterDeviceNotificationW)"); + + // initial device enumeration + enumeratePresentDevices(); + + } catch (Exception e) { + enumerationFailed(e); + return; + } + + // process messages + var msg = MSG.allocate(arena); + int err; + //noinspection StatementWithEmptyBody + while ((err = GetMessageW(errorState, msg, hwnd, 0, 0)) > 0) + ; // do nothing + + if (err == -1) + throwLastError(errorState, "internal error (GetMessageW)"); + } + } + + @SuppressWarnings("java:S106") + private void enumeratePresentDevices() { + + List deviceList = new ArrayList<>(); + try (var cleanup = new ScopeCleanup(); + var deviceInfoSet = DeviceInfoSet.ofPresentDevices(GUID_DEVINTERFACE_USB_DEVICE(), null)) { + + // ensure all hubs are closed later + final var hubHandles = new HashMap(); + cleanup.add(() -> hubHandles.forEach((_, handle) -> CloseHandle(handle))); + + // iterate all devices + while (deviceInfoSet.next()) { + + var instanceId = deviceInfoSet.getStringProperty(DEVPKEY_Device_InstanceId()); + var devicePath = DeviceInfoSet.getDevicePath(instanceId, GUID_DEVINTERFACE_USB_DEVICE()); + + try { + deviceList.add(createDeviceFromDeviceInfo(deviceInfoSet, devicePath, hubHandles)); + + } catch (Exception e) { + LOG.log(INFO, String.format("failed to retrieve information about device %s - ignoring device", devicePath), e); + } + } + + setInitialDeviceList(deviceList); + } + } + + private UsbDevice createDeviceFromDeviceInfo(DeviceInfoSet deviceInfoSet, String devicePath, + Map hubHandles) { + try (var arena = Arena.ofConfined()) { + + var usbPortNum = deviceInfoSet.getIntProperty(DEVPKEY_Device_Address()); + var parentInstanceId = deviceInfoSet.getStringProperty(DEVPKEY_Device_Parent()); + var hubPath = DeviceInfoSet.getDevicePath(parentInstanceId, GUID_DEVINTERFACE_USB_HUB()); + + // open hub if not open yet + var hubHandle = hubHandles.get(hubPath); + if (hubHandle == null) { + var hubPathSeg = arena.allocateFrom(hubPath, UTF_16LE); + var errorState = allocateErrorState(arena); + hubHandle = CreateFileW(errorState, hubPathSeg, GENERIC_WRITE, FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (Win.isInvalidHandle(hubHandle)) + throwLastError(errorState, "internal error (opening hub device)"); + hubHandles.put(hubPath, hubHandle); + } + + return createDevice(devicePath, deviceInfoSet.isCompositeDevice(), hubHandle, usbPortNum); + } + } + + /** + * Retrieve device descriptor and create {@code UsbDevice} instance + * + * @param devicePath the device path + * @param hubHandle the hub handle (parent) + * @param usbPortNum the USB port number + * @return the {@code UsbDevice} instance + */ + private UsbDevice createDevice(String devicePath, boolean isComposite, MemorySegment hubHandle, int usbPortNum) { + + try (var arena = Arena.ofConfined()) { + + // get device descriptor + var connInfo = USB_NODE_CONNECTION_INFORMATION_EX.allocate(arena, 0); + USB_NODE_CONNECTION_INFORMATION_EX.ConnectionIndex(connInfo, usbPortNum); + var sizeHolder = arena.allocate(JAVA_INT); + var errorState = allocateErrorState(arena); + if (DeviceIoControl(errorState, hubHandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, + connInfo, (int) connInfo.byteSize(), connInfo, (int) connInfo.byteSize(), sizeHolder, NULL) == 0) + throwLastError(errorState, "internal error (getting device descriptor failed)"); + + var descriptorSegment = USB_NODE_CONNECTION_INFORMATION_EX.DeviceDescriptor(connInfo); + var deviceDescriptor = new DeviceDescriptor(descriptorSegment); + + var vendorId = deviceDescriptor.vendorID(); + var productId = deviceDescriptor.productID(); + + var configDesc = getDescriptor(hubHandle, usbPortNum, CONFIGURATION_DESCRIPTOR_TYPE, 0, (short) 0, arena); + + // create new device + var device = new WindowsUsbDevice(devicePath, vendorId, productId, configDesc, isComposite); + device.setFromDeviceDescriptor(descriptorSegment); + + var languages = getLanguages(hubHandle, usbPortNum, arena); + device.setProductString(descriptorSegment, index -> getStringDescriptor(hubHandle, usbPortNum, index, languages)); + return device; + } + } + + private MemorySegment getDescriptor(MemorySegment hubHandle, int usbPortNumber, int descriptorType, int index, + short languageID, Arena arena) { + return getDescriptor(hubHandle, usbPortNumber, descriptorType, index, languageID, 0, arena); + + } + + private MemorySegment getDescriptor(MemorySegment hubHandle, int usbPortNumber, int descriptorType, int index, + short languageID, int requestSize, Arena arena) { + var size = requestSize != 0 ? requestSize + (int) REQUEST_DATA_OFFSET : 256; + + // create descriptor requests + var descriptorRequest = arena.allocate(size); + USB_DESCRIPTOR_REQUEST.ConnectionIndex(descriptorRequest, usbPortNumber); + var setupPacket = new SetupPacket(descriptorRequest.asSlice( + USB_DESCRIPTOR_REQUEST.SetupPacket_bmRequest$offset(), SetupPacket.LAYOUT.byteSize())); + setupPacket.setRequestType(0x80); // device-to-host / type standard / recipient device + setupPacket.setRequest(USB_REQUEST_GET_DESCRIPTOR); + setupPacket.setValue((descriptorType << 8) | index); + setupPacket.setIndex(languageID); + setupPacket.setLength(size - (int) REQUEST_DATA_OFFSET); + + // execute request + var effectiveSizeHolder = arena.allocate(JAVA_INT); + var errorState = allocateErrorState(arena); + if (DeviceIoControl(errorState, hubHandle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + descriptorRequest, size, descriptorRequest, size, effectiveSizeHolder, NULL) == 0) + throwLastError(errorState, "internal error (retrieving descriptor %d failed)", index); + + // determine size of descriptor + int expectedSize; + if (descriptorType != CONFIGURATION_DESCRIPTOR_TYPE) { + expectedSize = 255 & descriptorRequest.get(JAVA_BYTE, REQUEST_DATA_OFFSET); + } else { + var configDesc = + new ConfigurationDescriptor(descriptorRequest.asSlice(REQUEST_DATA_OFFSET, ConfigurationDescriptor.LAYOUT.byteSize())); + expectedSize = configDesc.totalLength(); + } + + // check against effective size + var effectiveSize = effectiveSizeHolder.get(JAVA_INT, 0) - REQUEST_DATA_OFFSET; + if (effectiveSize != expectedSize) { + if (requestSize != 0) + throwException("internal error (unexpected descriptor size)"); + + // repeat with correct size + return getDescriptor(hubHandle, usbPortNumber, descriptorType, index, languageID, expectedSize, arena); + } + + return descriptorRequest.asSlice(REQUEST_DATA_OFFSET, effectiveSize); + } + + @SuppressWarnings("java:S106") + private String getStringDescriptor(MemorySegment hubHandle, int usbPortNumber, int index, short[] languages) { + if (index == 0) + return null; + + try (var arena = Arena.ofConfined()) { + for (var language : languages) { + try { + var stringDesc = new StringDescriptor(getDescriptor(hubHandle, usbPortNumber, STRING_DESCRIPTOR_TYPE, + index, language, arena)); + return stringDesc.string(); + + } catch (UsbException _) { + // ignore and try next language + } + } + } + + // Even though this function is only called for string descriptors referenced in the + // configuration descriptor, some device might not provide them; so ignore it. + return null; + } + + private short[] getLanguages(MemorySegment hubHandle, int usbPortNumber, Arena arena) { + try { + var languages = getDescriptor(hubHandle, usbPortNumber, STRING_DESCRIPTOR_TYPE, 0, (short) 0, arena); + var n = (languages.byteSize() - 2) / 2; + if (n == 0) + return new short[]{DEFAULT_LANGUAGE}; + return languages.asSlice(2, n * 2).toArray(JAVA_SHORT); + } catch (UsbException _) { + return new short[]{DEFAULT_LANGUAGE}; + } + } + + @SuppressWarnings("java:S1144") + private long handleWindowMessage(MemorySegment hWnd, int uMsg, long wParam, long lParam) { + + // check for message related to connecting/disconnecting devices + if (uMsg == WM_DEVICECHANGE && (wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE)) { + var data = MemorySegment.ofAddress(lParam).reinterpret(DEV_BROADCAST_DEVICEINTERFACE_W.sizeof()); + if (DEV_BROADCAST_HDR.dbch_devicetype(data) == DBT_DEVTYP_DEVICEINTERFACE) { + + // get device path + var nameSlice = + MemorySegment.ofAddress(DEV_BROADCAST_DEVICEINTERFACE_W.dbcc_name(data).address()).reinterpret(500); + var devicePath = nameSlice.getString(0, UTF_16LE); + if (wParam == DBT_DEVICEARRIVAL) + onDeviceConnected(devicePath); + else + onDeviceDisconnected(devicePath); + return 0; + } + } + + // default message handling + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + + @SuppressWarnings("java:S106") + private void onDeviceConnected(String devicePath) { + try (var cleanup = new ScopeCleanup(); + var deviceInfoSet = DeviceInfoSet.ofPath(devicePath)) { + + // ensure all hubs are closed later + final var hubHandles = new HashMap(); + cleanup.add(() -> hubHandles.forEach((_, handle) -> CloseHandle(handle))); + + try { + // create device instance + var device = createDeviceFromDeviceInfo(deviceInfoSet, devicePath, hubHandles); + + // add it to device list + addDevice(device); + + } catch (Exception e) { + LOG.log(INFO, String.format("failed to retrieve information about device %s - ignoring device", devicePath), e); + } + } + } + + private void onDeviceDisconnected(String devicePath) { + closeAndRemoveDevice(devicePath); + } + + /** + * Finds the index of the device in the list. + *

+ * This override uses a case-insensitive string comparison as Windows uses different casing + * when initially enumerating devices and during later monitoring. + *

+ * + * @param deviceList the device list + * @param deviceId the unique device ID + * @return index, or -1 if not found + */ + @Override + protected int findDeviceIndex(List deviceList, Object deviceId) { + var id = deviceId.toString(); + for (var i = 0; i < deviceList.size(); i++) { + var dev = (UsbDeviceImpl) deviceList.get(i); + if (id.equalsIgnoreCase(dev.getUniqueId().toString())) + return i; + } + return -1; + } +} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBException.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbException.java similarity index 62% rename from java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBException.java rename to java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbException.java index 7b93a575..94f70bf5 100644 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBException.java +++ b/java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUsbException.java @@ -6,22 +6,30 @@ // package net.codecrete.usb.windows; -import net.codecrete.usb.USBException; -import net.codecrete.usb.USBStallException; -import net.codecrete.usb.windows.gen.kernel32.Kernel32; -import net.codecrete.usb.windows.gen.ntdll.NtDll; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbStallException; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import static java.lang.foreign.MemorySegment.NULL; import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.nio.charset.StandardCharsets.UTF_16LE; import static net.codecrete.usb.common.ForeignMemory.dereference; +import static windows.win32.foundation.Apis.LocalFree; +import static windows.win32.foundation.Constants.STATUS_UNSUCCESSFUL; +import static windows.win32.foundation.WIN32_ERROR.ERROR_GEN_FAILURE; +import static windows.win32.system.diagnostics.debug.Apis.FormatMessageW; +import static windows.win32.system.diagnostics.debug.FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_ALLOCATE_BUFFER; +import static windows.win32.system.diagnostics.debug.FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_FROM_HMODULE; +import static windows.win32.system.diagnostics.debug.FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_FROM_SYSTEM; +import static windows.win32.system.diagnostics.debug.FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_IGNORE_INSERTS; +import static windows.win32.system.libraryloader.Apis.GetModuleHandleW; /** * Exception thrown if a Windows specific error occurs. */ -public class WindowsUSBException extends USBException { +public class WindowsUsbException extends UsbException { /** * Creates a new instance. @@ -32,7 +40,7 @@ public class WindowsUSBException extends USBException { * @param message exception message * @param errorCode Windows error code (usually returned from {@code GetLastError()}) */ - public WindowsUSBException(String message, int errorCode) { + public WindowsUsbException(String message, int errorCode) { super(String.format("%s: %s", message, getErrorMessage(errorCode)), errorCode); } @@ -48,10 +56,10 @@ public WindowsUSBException(String message, int errorCode) { */ static void throwException(int errorCode, String message, Object... args) { var formattedMessage = String.format(message, args); - if (errorCode == Kernel32.ERROR_GEN_FAILURE() || errorCode == NtDll.STATUS_UNSUCCESSFUL()) { - throw new USBStallException(formattedMessage); + if (errorCode == ERROR_GEN_FAILURE || errorCode == STATUS_UNSUCCESSFUL) { + throw new UsbStallException(formattedMessage); } else { - throw new WindowsUSBException(formattedMessage, errorCode); + throw new WindowsUsbException(formattedMessage, errorCode); } } @@ -62,7 +70,7 @@ static void throwException(int errorCode, String message, Object... args) { * @param args arguments for exception message */ static void throwException(String message, Object... args) { - throw new USBException(String.format(message, args)); + throw new UsbException(String.format(message, args)); } /** @@ -85,8 +93,9 @@ static void throwLastError(MemorySegment errorState, String message, Object... a private static MemorySegment getNtModule() { if (ntModule == null) { try (var arena = Arena.ofConfined()) { - var moduleName = Win.createSegmentFromString("NTDLL.DLL", arena); - ntModule = Kernel32.GetModuleHandleW(moduleName); + var errorState = Win.allocateErrorState(arena); + var moduleName = arena.allocateFrom("NTDLL.DLL", UTF_16LE); + ntModule = GetModuleHandleW(errorState, moduleName); } } @@ -95,17 +104,18 @@ private static MemorySegment getNtModule() { static String getErrorMessage(int errorCode) { try (var arena = Arena.ofConfined()) { + var errorState = Win.allocateErrorState(arena); var messagePointerHolder = arena.allocate(ADDRESS); // First try: Win32 error code - var res = Kernel32.FormatMessageW( - Kernel32.FORMAT_MESSAGE_ALLOCATE_BUFFER() | Kernel32.FORMAT_MESSAGE_FROM_SYSTEM() | Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS(), + var res = FormatMessageW( + errorState, FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, messagePointerHolder, 0, NULL); // Second try: NTSTATUS error code if (res == 0) { - res = Kernel32.FormatMessageW( - Kernel32.FORMAT_MESSAGE_ALLOCATE_BUFFER() | Kernel32.FORMAT_MESSAGE_FROM_HMODULE() | Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS(), + res = FormatMessageW( + errorState, FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, getNtModule(), errorCode, 0, messagePointerHolder, 0, NULL); } @@ -114,8 +124,8 @@ static String getErrorMessage(int errorCode) { return "unspecified error"; var messagePointer = dereference(messagePointerHolder).reinterpret(128 * 1024); // NOSONAR - var message = Win.createStringFromSegment(messagePointer); - Kernel32.LocalFree(messagePointer); + var message = messagePointer.getString(0, UTF_16LE); + LocalFree(errorState, messagePointer); return message.trim(); } } diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/Advapi32.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/Advapi32.java deleted file mode 100644 index 6152d8c1..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/Advapi32.java +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.advapi32; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class Advapi32 { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle RegCloseKey$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"RegCloseKey"); - } - /** - * {@snippet : - * LSTATUS RegCloseKey(HKEY hKey); - * } - */ - public static int RegCloseKey(MemorySegment hKey) { - var mh$ = RegCloseKey$MH(); - try { - return (int)mh$.invokeExact(hKey); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static MethodHandle RegQueryValueExW$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$3,"RegQueryValueExW"); - } - /** - * {@snippet : - * LSTATUS RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); - * } - */ - public static int RegQueryValueExW(MemorySegment hKey, MemorySegment lpValueName, MemorySegment lpReserved, MemorySegment lpType, MemorySegment lpData, MemorySegment lpcbData) { - var mh$ = RegQueryValueExW$MH(); - try { - return (int)mh$.invokeExact(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - /** - * {@snippet : - * #define KEY_READ 131097 - * } - */ - public static int KEY_READ() { - return (int)131097L; - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/RuntimeHelper.java deleted file mode 100644 index 868da383..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.advapi32; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("Advapi32"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/constants$0.java deleted file mode 100644 index ee2a9f73..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/advapi32/constants$0.java +++ /dev/null @@ -1,34 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.advapi32; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "RegCloseKey", - constants$0.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "RegQueryValueExW", - constants$0.const$2 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/GUID.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/GUID.java deleted file mode 100644 index 85b02bc1..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/GUID.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -/** - * {@snippet : - * typedef struct _GUID GUID; - * } - */ -public final class GUID extends _GUID { - - // Suppresses default constructor, ensuring non-instantiability. - private GUID() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/Kernel32.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/Kernel32.java deleted file mode 100644 index 4561b07f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/Kernel32.java +++ /dev/null @@ -1,238 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class Kernel32 { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define FILE_SHARE_READ 1 - * } - */ - public static int FILE_SHARE_READ() { - return (int)1L; - } - /** - * {@snippet : - * #define FILE_SHARE_WRITE 2 - * } - */ - public static int FILE_SHARE_WRITE() { - return (int)2L; - } - /** - * {@snippet : - * #define FILE_ATTRIBUTE_NORMAL 128 - * } - */ - public static int FILE_ATTRIBUTE_NORMAL() { - return (int)128L; - } - /** - * {@snippet : - * #define OPEN_EXISTING 3 - * } - */ - public static int OPEN_EXISTING() { - return (int)3L; - } - /** - * {@snippet : - * #define FILE_FLAG_OVERLAPPED 1073741824 - * } - */ - public static int FILE_FLAG_OVERLAPPED() { - return (int)1073741824L; - } - /** - * {@snippet : - * #define FORMAT_MESSAGE_ALLOCATE_BUFFER 256 - * } - */ - public static int FORMAT_MESSAGE_ALLOCATE_BUFFER() { - return (int)256L; - } - /** - * {@snippet : - * #define FORMAT_MESSAGE_IGNORE_INSERTS 512 - * } - */ - public static int FORMAT_MESSAGE_IGNORE_INSERTS() { - return (int)512L; - } - /** - * {@snippet : - * #define FORMAT_MESSAGE_FROM_HMODULE 2048 - * } - */ - public static int FORMAT_MESSAGE_FROM_HMODULE() { - return (int)2048L; - } - /** - * {@snippet : - * #define FORMAT_MESSAGE_FROM_SYSTEM 4096 - * } - */ - public static int FORMAT_MESSAGE_FROM_SYSTEM() { - return (int)4096L; - } - public static MethodHandle CloseHandle$MH() { - return RuntimeHelper.requireNonNull(constants$1.const$6,"CloseHandle"); - } - /** - * {@snippet : - * BOOL CloseHandle(HANDLE hObject); - * } - */ - public static int CloseHandle(MemorySegment hObject) { - var mh$ = CloseHandle$MH(); - try { - return (int)mh$.invokeExact(hObject); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static MethodHandle GetModuleHandleW$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$1,"GetModuleHandleW"); - } - /** - * {@snippet : - * HMODULE GetModuleHandleW(LPCWSTR lpModuleName); - * } - */ - public static MemorySegment GetModuleHandleW(MemorySegment lpModuleName) { - var mh$ = GetModuleHandleW$MH(); - try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(lpModuleName); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static MethodHandle LocalFree$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$2,"LocalFree"); - } - /** - * {@snippet : - * HLOCAL LocalFree(HLOCAL hMem); - * } - */ - public static MemorySegment LocalFree(MemorySegment hMem) { - var mh$ = LocalFree$MH(); - try { - return (java.lang.foreign.MemorySegment)mh$.invokeExact(hMem); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static MethodHandle FormatMessageW$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$4,"FormatMessageW"); - } - /** - * {@snippet : - * DWORD FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list* Arguments); - * } - */ - public static int FormatMessageW(int dwFlags, MemorySegment lpSource, int dwMessageId, int dwLanguageId, MemorySegment lpBuffer, int nSize, MemorySegment Arguments) { - var mh$ = FormatMessageW$MH(); - try { - return (int)mh$.invokeExact(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - /** - * {@snippet : - * #define GENERIC_READ 2147483648 - * } - */ - public static int GENERIC_READ() { - return (int)2147483648L; - } - /** - * {@snippet : - * #define GENERIC_WRITE 1073741824 - * } - */ - public static int GENERIC_WRITE() { - return (int)1073741824L; - } - /** - * {@snippet : - * #define INFINITE 4294967295 - * } - */ - public static int INFINITE() { - return (int)4294967295L; - } - /** - * {@snippet : - * #define ERROR_FILE_NOT_FOUND 2 - * } - */ - public static int ERROR_FILE_NOT_FOUND() { - return (int)2L; - } - /** - * {@snippet : - * #define ERROR_GEN_FAILURE 31 - * } - */ - public static int ERROR_GEN_FAILURE() { - return (int)31L; - } - /** - * {@snippet : - * #define ERROR_INSUFFICIENT_BUFFER 122 - * } - */ - public static int ERROR_INSUFFICIENT_BUFFER() { - return (int)122L; - } - /** - * {@snippet : - * #define ERROR_MORE_DATA 234 - * } - */ - public static int ERROR_MORE_DATA() { - return (int)234L; - } - /** - * {@snippet : - * #define ERROR_NO_MORE_ITEMS 259 - * } - */ - public static int ERROR_NO_MORE_ITEMS() { - return (int)259L; - } - /** - * {@snippet : - * #define ERROR_IO_PENDING 997 - * } - */ - public static int ERROR_IO_PENDING() { - return (int)997L; - } - /** - * {@snippet : - * #define ERROR_NOT_FOUND 1168 - * } - */ - public static int ERROR_NOT_FOUND() { - return (int)1168L; - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/OVERLAPPED.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/OVERLAPPED.java deleted file mode 100644 index 129b9892..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/OVERLAPPED.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -/** - * {@snippet : - * typedef struct _OVERLAPPED OVERLAPPED; - * } - */ -public final class OVERLAPPED extends _OVERLAPPED { - - // Suppresses default constructor, ensuring non-instantiability. - private OVERLAPPED() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/RuntimeHelper.java deleted file mode 100644 index 2f61c112..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.kernel32; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("Kernel32"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_GUID.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_GUID.java deleted file mode 100644 index ead65d4b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_GUID.java +++ /dev/null @@ -1,117 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _GUID { - * unsigned long Data1; - * unsigned short Data2; - * unsigned short Data3; - * unsigned char Data4[8]; - * }; - * } - */ -public class _GUID { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; - } - public static VarHandle Data1$VH() { - return constants$0.const$1; - } - /** - * Getter for field: - * {@snippet : - * unsigned long Data1; - * } - */ - public static int Data1$get(MemorySegment seg) { - return (int)constants$0.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * unsigned long Data1; - * } - */ - public static void Data1$set(MemorySegment seg, int x) { - constants$0.const$1.set(seg, x); - } - public static int Data1$get(MemorySegment seg, long index) { - return (int)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void Data1$set(MemorySegment seg, long index, int x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Data2$VH() { - return constants$0.const$2; - } - /** - * Getter for field: - * {@snippet : - * unsigned short Data2; - * } - */ - public static short Data2$get(MemorySegment seg) { - return (short)constants$0.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * unsigned short Data2; - * } - */ - public static void Data2$set(MemorySegment seg, short x) { - constants$0.const$2.set(seg, x); - } - public static short Data2$get(MemorySegment seg, long index) { - return (short)constants$0.const$2.get(seg.asSlice(index*sizeof())); - } - public static void Data2$set(MemorySegment seg, long index, short x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Data3$VH() { - return constants$0.const$3; - } - /** - * Getter for field: - * {@snippet : - * unsigned short Data3; - * } - */ - public static short Data3$get(MemorySegment seg) { - return (short)constants$0.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * unsigned short Data3; - * } - */ - public static void Data3$set(MemorySegment seg, short x) { - constants$0.const$3.set(seg, x); - } - public static short Data3$get(MemorySegment seg, long index) { - return (short)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void Data3$set(MemorySegment seg, long index, short x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment Data4$slice(MemorySegment seg) { - return seg.asSlice(8, 8); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_OVERLAPPED.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_OVERLAPPED.java deleted file mode 100644 index 770014d6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/_OVERLAPPED.java +++ /dev/null @@ -1,201 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _OVERLAPPED { - * ULONG_PTR Internal; - * ULONG_PTR InternalHigh; - * union { - * struct { - * DWORD Offset; - * DWORD OffsetHigh; - * }; - * PVOID Pointer; - * }; - * HANDLE hEvent; - * }; - * } - */ -public class _OVERLAPPED { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$4; - } - public static VarHandle Internal$VH() { - return constants$0.const$5; - } - /** - * Getter for field: - * {@snippet : - * ULONG_PTR Internal; - * } - */ - public static long Internal$get(MemorySegment seg) { - return (long)constants$0.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG_PTR Internal; - * } - */ - public static void Internal$set(MemorySegment seg, long x) { - constants$0.const$5.set(seg, x); - } - public static long Internal$get(MemorySegment seg, long index) { - return (long)constants$0.const$5.get(seg.asSlice(index*sizeof())); - } - public static void Internal$set(MemorySegment seg, long index, long x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle InternalHigh$VH() { - return constants$1.const$0; - } - /** - * Getter for field: - * {@snippet : - * ULONG_PTR InternalHigh; - * } - */ - public static long InternalHigh$get(MemorySegment seg) { - return (long)constants$1.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG_PTR InternalHigh; - * } - */ - public static void InternalHigh$set(MemorySegment seg, long x) { - constants$1.const$0.set(seg, x); - } - public static long InternalHigh$get(MemorySegment seg, long index) { - return (long)constants$1.const$0.get(seg.asSlice(index*sizeof())); - } - public static void InternalHigh$set(MemorySegment seg, long index, long x) { - constants$1.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Offset$VH() { - return constants$1.const$1; - } - /** - * Getter for field: - * {@snippet : - * DWORD Offset; - * } - */ - public static int Offset$get(MemorySegment seg) { - return (int)constants$1.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD Offset; - * } - */ - public static void Offset$set(MemorySegment seg, int x) { - constants$1.const$1.set(seg, x); - } - public static int Offset$get(MemorySegment seg, long index) { - return (int)constants$1.const$1.get(seg.asSlice(index*sizeof())); - } - public static void Offset$set(MemorySegment seg, long index, int x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle OffsetHigh$VH() { - return constants$1.const$2; - } - /** - * Getter for field: - * {@snippet : - * DWORD OffsetHigh; - * } - */ - public static int OffsetHigh$get(MemorySegment seg) { - return (int)constants$1.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD OffsetHigh; - * } - */ - public static void OffsetHigh$set(MemorySegment seg, int x) { - constants$1.const$2.set(seg, x); - } - public static int OffsetHigh$get(MemorySegment seg, long index) { - return (int)constants$1.const$2.get(seg.asSlice(index*sizeof())); - } - public static void OffsetHigh$set(MemorySegment seg, long index, int x) { - constants$1.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Pointer$VH() { - return constants$1.const$3; - } - /** - * Getter for field: - * {@snippet : - * PVOID Pointer; - * } - */ - public static MemorySegment Pointer$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * PVOID Pointer; - * } - */ - public static void Pointer$set(MemorySegment seg, MemorySegment x) { - constants$1.const$3.set(seg, x); - } - public static MemorySegment Pointer$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void Pointer$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hEvent$VH() { - return constants$1.const$4; - } - /** - * Getter for field: - * {@snippet : - * HANDLE hEvent; - * } - */ - public static MemorySegment hEvent$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HANDLE hEvent; - * } - */ - public static void hEvent$set(MemorySegment seg, MemorySegment x) { - constants$1.const$4.set(seg, x); - } - public static MemorySegment hEvent$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$4.get(seg.asSlice(index*sizeof())); - } - public static void hEvent$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$0.java deleted file mode 100644 index 18b60b9b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$0.java +++ /dev/null @@ -1,38 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withName("Data1"), - JAVA_SHORT.withName("Data2"), - JAVA_SHORT.withName("Data3"), - MemoryLayout.sequenceLayout(8, JAVA_BYTE).withName("Data4") - ).withName("_GUID"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("Data1")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("Data2")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("Data3")); - static final StructLayout const$4 = MemoryLayout.structLayout( - JAVA_LONG.withName("Internal"), - JAVA_LONG.withName("InternalHigh"), - MemoryLayout.unionLayout( - MemoryLayout.structLayout( - JAVA_INT.withName("Offset"), - JAVA_INT.withName("OffsetHigh") - ).withName("$anon$0"), - RuntimeHelper.POINTER.withName("Pointer") - ).withName("$anon$0"), - RuntimeHelper.POINTER.withName("hEvent") - ).withName("_OVERLAPPED"); - static final VarHandle const$5 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("Internal")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$1.java deleted file mode 100644 index b86794ff..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$1.java +++ /dev/null @@ -1,29 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final VarHandle const$0 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("InternalHigh")); - static final VarHandle const$1 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("Offset")); - static final VarHandle const$2 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("OffsetHigh")); - static final VarHandle const$3 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("$anon$0"), MemoryLayout.PathElement.groupElement("Pointer")); - static final VarHandle const$4 = constants$0.const$4.varHandle(MemoryLayout.PathElement.groupElement("hEvent")); - static final FunctionDescriptor const$5 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$6 = RuntimeHelper.downcallHandle( - "CloseHandle", - constants$1.const$5 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$2.java deleted file mode 100644 index 0f426d9c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/kernel32/constants$2.java +++ /dev/null @@ -1,39 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.kernel32; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "GetModuleHandleW", - constants$2.const$0 - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "LocalFree", - constants$2.const$0 - ); - static final FunctionDescriptor const$3 = FunctionDescriptor.of(JAVA_INT, - JAVA_INT, - RuntimeHelper.POINTER, - JAVA_INT, - JAVA_INT, - RuntimeHelper.POINTER, - JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$4 = RuntimeHelper.downcallHandle( - "FormatMessageW", - constants$2.const$3 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/NtDll.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/NtDll.java deleted file mode 100644 index c7dbf69a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/NtDll.java +++ /dev/null @@ -1,28 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.ntdll; - -import java.lang.foreign.AddressLayout; - -import static java.lang.foreign.ValueLayout.*; -public class NtDll { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define STATUS_UNSUCCESSFUL -1073741823 - * } - */ - public static int STATUS_UNSUCCESSFUL() { - return (int)-1073741823L; - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/RuntimeHelper.java deleted file mode 100644 index 45bfd22b..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.ntdll; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/constants$0.java deleted file mode 100644 index 7bb245f6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ntdll/constants$0.java +++ /dev/null @@ -1,11 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.ntdll; - -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/Ole32.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/Ole32.java deleted file mode 100644 index 15bc34d0..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/Ole32.java +++ /dev/null @@ -1,38 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.ole32; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class Ole32 { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - public static MethodHandle CLSIDFromString$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"CLSIDFromString"); - } - /** - * {@snippet : - * HRESULT CLSIDFromString(LPCOLESTR lpsz, LPCLSID pclsid); - * } - */ - public static int CLSIDFromString(MemorySegment lpsz, MemorySegment pclsid) { - var mh$ = CLSIDFromString$MH(); - try { - return (int)mh$.invokeExact(lpsz, pclsid); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/RuntimeHelper.java deleted file mode 100644 index c58af8c4..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.ole32; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("Ole32"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/constants$0.java deleted file mode 100644 index bf4c2c05..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/ole32/constants$0.java +++ /dev/null @@ -1,23 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.ole32; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "CLSIDFromString", - constants$0.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/DEVPROPKEY.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/DEVPROPKEY.java deleted file mode 100644 index 8162d9a9..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/DEVPROPKEY.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -/** - * {@snippet : - * typedef struct _DEVPROPKEY DEVPROPKEY; - * } - */ -public final class DEVPROPKEY extends _DEVPROPKEY { - - // Suppresses default constructor, ensuring non-instantiability. - private DEVPROPKEY() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/RuntimeHelper.java deleted file mode 100644 index 6a51526d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.setupapi; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("SetupAPI"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DATA.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DATA.java deleted file mode 100644 index 13425fec..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DATA.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -/** - * {@snippet : - * typedef struct _SP_DEVICE_INTERFACE_DATA SP_DEVICE_INTERFACE_DATA; - * } - */ -public final class SP_DEVICE_INTERFACE_DATA extends _SP_DEVICE_INTERFACE_DATA { - - // Suppresses default constructor, ensuring non-instantiability. - private SP_DEVICE_INTERFACE_DATA() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DETAIL_DATA_W.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DETAIL_DATA_W.java deleted file mode 100644 index 7a9f76bc..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVICE_INTERFACE_DETAIL_DATA_W.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -/** - * {@snippet : - * typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W SP_DEVICE_INTERFACE_DETAIL_DATA_W; - * } - */ -public final class SP_DEVICE_INTERFACE_DETAIL_DATA_W extends _SP_DEVICE_INTERFACE_DETAIL_DATA_W { - - // Suppresses default constructor, ensuring non-instantiability. - private SP_DEVICE_INTERFACE_DETAIL_DATA_W() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVINFO_DATA.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVINFO_DATA.java deleted file mode 100644 index ebc94bce..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SP_DEVINFO_DATA.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -/** - * {@snippet : - * typedef struct _SP_DEVINFO_DATA SP_DEVINFO_DATA; - * } - */ -public final class SP_DEVINFO_DATA extends _SP_DEVINFO_DATA { - - // Suppresses default constructor, ensuring non-instantiability. - private SP_DEVINFO_DATA() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SetupAPI.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SetupAPI.java deleted file mode 100644 index bccea11d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/SetupAPI.java +++ /dev/null @@ -1,110 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class SetupAPI { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define DEVPROP_TYPEMOD_LIST 8192 - * } - */ - public static int DEVPROP_TYPEMOD_LIST() { - return (int)8192L; - } - /** - * {@snippet : - * #define DEVPROP_TYPE_UINT32 7 - * } - */ - public static int DEVPROP_TYPE_UINT32() { - return (int)7L; - } - /** - * {@snippet : - * #define DEVPROP_TYPE_STRING 18 - * } - */ - public static int DEVPROP_TYPE_STRING() { - return (int)18L; - } - /** - * {@snippet : - * #define DICS_FLAG_GLOBAL 1 - * } - */ - public static int DICS_FLAG_GLOBAL() { - return (int)1L; - } - /** - * {@snippet : - * #define DIGCF_PRESENT 2 - * } - */ - public static int DIGCF_PRESENT() { - return (int)2L; - } - /** - * {@snippet : - * #define DIGCF_DEVICEINTERFACE 16 - * } - */ - public static int DIGCF_DEVICEINTERFACE() { - return (int)16L; - } - /** - * {@snippet : - * #define DIREG_DEV 1 - * } - */ - public static int DIREG_DEV() { - return (int)1L; - } - public static MethodHandle SetupDiDestroyDeviceInfoList$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$1,"SetupDiDestroyDeviceInfoList"); - } - /** - * {@snippet : - * BOOL SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet); - * } - */ - public static int SetupDiDestroyDeviceInfoList(MemorySegment DeviceInfoSet) { - var mh$ = SetupDiDestroyDeviceInfoList$MH(); - try { - return (int)mh$.invokeExact(DeviceInfoSet); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static MethodHandle SetupDiDeleteDeviceInterfaceData$MH() { - return RuntimeHelper.requireNonNull(constants$2.const$3,"SetupDiDeleteDeviceInterfaceData"); - } - /** - * {@snippet : - * BOOL SetupDiDeleteDeviceInterfaceData(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData); - * } - */ - public static int SetupDiDeleteDeviceInterfaceData(MemorySegment DeviceInfoSet, MemorySegment DeviceInterfaceData) { - var mh$ = SetupDiDeleteDeviceInterfaceData$MH(); - try { - return (int)mh$.invokeExact(DeviceInfoSet, DeviceInterfaceData); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_DEVPROPKEY.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_DEVPROPKEY.java deleted file mode 100644 index 8389d24a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_DEVPROPKEY.java +++ /dev/null @@ -1,61 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _DEVPROPKEY { - * DEVPROPGUID fmtid; - * DEVPROPID pid; - * }; - * } - */ -public class _DEVPROPKEY { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; - } - public static MemorySegment fmtid$slice(MemorySegment seg) { - return seg.asSlice(0, 16); - } - public static VarHandle pid$VH() { - return constants$0.const$1; - } - /** - * Getter for field: - * {@snippet : - * DEVPROPID pid; - * } - */ - public static int pid$get(MemorySegment seg) { - return (int)constants$0.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DEVPROPID pid; - * } - */ - public static void pid$set(MemorySegment seg, int x) { - constants$0.const$1.set(seg, x); - } - public static int pid$get(MemorySegment seg, long index) { - return (int)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void pid$set(MemorySegment seg, long index, int x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DATA.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DATA.java deleted file mode 100644 index c1b5e09f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DATA.java +++ /dev/null @@ -1,117 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _SP_DEVICE_INTERFACE_DATA { - * DWORD cbSize; - * GUID InterfaceClassGuid; - * DWORD Flags; - * ULONG_PTR Reserved; - * }; - * } - */ -public class _SP_DEVICE_INTERFACE_DATA { - - public static MemoryLayout $LAYOUT() { - return constants$1.const$0; - } - public static VarHandle cbSize$VH() { - return constants$1.const$1; - } - /** - * Getter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static int cbSize$get(MemorySegment seg) { - return (int)constants$1.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static void cbSize$set(MemorySegment seg, int x) { - constants$1.const$1.set(seg, x); - } - public static int cbSize$get(MemorySegment seg, long index) { - return (int)constants$1.const$1.get(seg.asSlice(index*sizeof())); - } - public static void cbSize$set(MemorySegment seg, long index, int x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment InterfaceClassGuid$slice(MemorySegment seg) { - return seg.asSlice(4, 16); - } - public static VarHandle Flags$VH() { - return constants$1.const$2; - } - /** - * Getter for field: - * {@snippet : - * DWORD Flags; - * } - */ - public static int Flags$get(MemorySegment seg) { - return (int)constants$1.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD Flags; - * } - */ - public static void Flags$set(MemorySegment seg, int x) { - constants$1.const$2.set(seg, x); - } - public static int Flags$get(MemorySegment seg, long index) { - return (int)constants$1.const$2.get(seg.asSlice(index*sizeof())); - } - public static void Flags$set(MemorySegment seg, long index, int x) { - constants$1.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Reserved$VH() { - return constants$1.const$3; - } - /** - * Getter for field: - * {@snippet : - * ULONG_PTR Reserved; - * } - */ - public static long Reserved$get(MemorySegment seg) { - return (long)constants$1.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG_PTR Reserved; - * } - */ - public static void Reserved$set(MemorySegment seg, long x) { - constants$1.const$3.set(seg, x); - } - public static long Reserved$get(MemorySegment seg, long index) { - return (long)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void Reserved$set(MemorySegment seg, long index, long x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DETAIL_DATA_W.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DETAIL_DATA_W.java deleted file mode 100644 index 4a837e91..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVICE_INTERFACE_DETAIL_DATA_W.java +++ /dev/null @@ -1,61 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W { - * DWORD cbSize; - * WCHAR DevicePath[1]; - * }; - * } - */ -public class _SP_DEVICE_INTERFACE_DETAIL_DATA_W { - - public static MemoryLayout $LAYOUT() { - return constants$1.const$4; - } - public static VarHandle cbSize$VH() { - return constants$1.const$5; - } - /** - * Getter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static int cbSize$get(MemorySegment seg) { - return (int)constants$1.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static void cbSize$set(MemorySegment seg, int x) { - constants$1.const$5.set(seg, x); - } - public static int cbSize$get(MemorySegment seg, long index) { - return (int)constants$1.const$5.get(seg.asSlice(index*sizeof())); - } - public static void cbSize$set(MemorySegment seg, long index, int x) { - constants$1.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment DevicePath$slice(MemorySegment seg) { - return seg.asSlice(4, 2); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVINFO_DATA.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVINFO_DATA.java deleted file mode 100644 index 8cf558b5..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/_SP_DEVINFO_DATA.java +++ /dev/null @@ -1,117 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _SP_DEVINFO_DATA { - * DWORD cbSize; - * GUID ClassGuid; - * DWORD DevInst; - * ULONG_PTR Reserved; - * }; - * } - */ -public class _SP_DEVINFO_DATA { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$2; - } - public static VarHandle cbSize$VH() { - return constants$0.const$3; - } - /** - * Getter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static int cbSize$get(MemorySegment seg) { - return (int)constants$0.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD cbSize; - * } - */ - public static void cbSize$set(MemorySegment seg, int x) { - constants$0.const$3.set(seg, x); - } - public static int cbSize$get(MemorySegment seg, long index) { - return (int)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void cbSize$set(MemorySegment seg, long index, int x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment ClassGuid$slice(MemorySegment seg) { - return seg.asSlice(4, 16); - } - public static VarHandle DevInst$VH() { - return constants$0.const$4; - } - /** - * Getter for field: - * {@snippet : - * DWORD DevInst; - * } - */ - public static int DevInst$get(MemorySegment seg) { - return (int)constants$0.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD DevInst; - * } - */ - public static void DevInst$set(MemorySegment seg, int x) { - constants$0.const$4.set(seg, x); - } - public static int DevInst$get(MemorySegment seg, long index) { - return (int)constants$0.const$4.get(seg.asSlice(index*sizeof())); - } - public static void DevInst$set(MemorySegment seg, long index, int x) { - constants$0.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Reserved$VH() { - return constants$0.const$5; - } - /** - * Getter for field: - * {@snippet : - * ULONG_PTR Reserved; - * } - */ - public static long Reserved$get(MemorySegment seg) { - return (long)constants$0.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG_PTR Reserved; - * } - */ - public static void Reserved$set(MemorySegment seg, long x) { - constants$0.const$5.set(seg, x); - } - public static long Reserved$get(MemorySegment seg, long index) { - return (long)constants$0.const$5.get(seg.asSlice(index*sizeof())); - } - public static void Reserved$set(MemorySegment seg, long index, long x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$0.java deleted file mode 100644 index e5d398cb..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$0.java +++ /dev/null @@ -1,40 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - MemoryLayout.structLayout( - JAVA_INT.withName("Data1"), - JAVA_SHORT.withName("Data2"), - JAVA_SHORT.withName("Data3"), - MemoryLayout.sequenceLayout(8, JAVA_BYTE).withName("Data4") - ).withName("fmtid"), - JAVA_INT.withName("pid") - ).withName("_DEVPROPKEY"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("pid")); - static final StructLayout const$2 = MemoryLayout.structLayout( - JAVA_INT.withName("cbSize"), - MemoryLayout.structLayout( - JAVA_INT.withName("Data1"), - JAVA_SHORT.withName("Data2"), - JAVA_SHORT.withName("Data3"), - MemoryLayout.sequenceLayout(8, JAVA_BYTE).withName("Data4") - ).withName("ClassGuid"), - JAVA_INT.withName("DevInst"), - JAVA_LONG.withName("Reserved") - ).withName("_SP_DEVINFO_DATA"); - static final VarHandle const$3 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("cbSize")); - static final VarHandle const$4 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("DevInst")); - static final VarHandle const$5 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("Reserved")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$1.java deleted file mode 100644 index 08aa9ba2..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$1.java +++ /dev/null @@ -1,36 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withName("cbSize"), - MemoryLayout.structLayout( - JAVA_INT.withName("Data1"), - JAVA_SHORT.withName("Data2"), - JAVA_SHORT.withName("Data3"), - MemoryLayout.sequenceLayout(8, JAVA_BYTE).withName("Data4") - ).withName("InterfaceClassGuid"), - JAVA_INT.withName("Flags"), - JAVA_LONG.withName("Reserved") - ).withName("_SP_DEVICE_INTERFACE_DATA"); - static final VarHandle const$1 = constants$1.const$0.varHandle(MemoryLayout.PathElement.groupElement("cbSize")); - static final VarHandle const$2 = constants$1.const$0.varHandle(MemoryLayout.PathElement.groupElement("Flags")); - static final VarHandle const$3 = constants$1.const$0.varHandle(MemoryLayout.PathElement.groupElement("Reserved")); - static final StructLayout const$4 = MemoryLayout.structLayout( - JAVA_INT.withName("cbSize"), - MemoryLayout.sequenceLayout(1, JAVA_SHORT).withName("DevicePath"), - MemoryLayout.paddingLayout(2) - ).withName("_SP_DEVICE_INTERFACE_DETAIL_DATA_W"); - static final VarHandle const$5 = constants$1.const$4.varHandle(MemoryLayout.PathElement.groupElement("cbSize")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$2.java deleted file mode 100644 index 5c778a87..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/setupapi/constants$2.java +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.setupapi; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "SetupDiDestroyDeviceInfoList", - constants$2.const$0 - ); - static final FunctionDescriptor const$2 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER, - RuntimeHelper.POINTER - ); - static final MethodHandle const$3 = RuntimeHelper.downcallHandle( - "SetupDiDeleteDeviceInterfaceData", - constants$2.const$2 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/RuntimeHelper.java deleted file mode 100644 index 099b08e3..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.usbioctl; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USBIoctl.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USBIoctl.java deleted file mode 100644 index 60c3662a..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USBIoctl.java +++ /dev/null @@ -1,36 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.AddressLayout; - -import static java.lang.foreign.ValueLayout.*; -public class USBIoctl { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 2229264 - * } - */ - public static int IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION() { - return (int)2229264L; - } - /** - * {@snippet : - * #define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX 2229320 - * } - */ - public static int IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX() { - return (int)2229320L; - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_DESCRIPTOR_REQUEST.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_DESCRIPTOR_REQUEST.java deleted file mode 100644 index 6a5de025..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_DESCRIPTOR_REQUEST.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -/** - * {@snippet : - * typedef struct _USB_DESCRIPTOR_REQUEST USB_DESCRIPTOR_REQUEST; - * } - */ -public final class USB_DESCRIPTOR_REQUEST extends _USB_DESCRIPTOR_REQUEST { - - // Suppresses default constructor, ensuring non-instantiability. - private USB_DESCRIPTOR_REQUEST() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_NODE_CONNECTION_INFORMATION_EX.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_NODE_CONNECTION_INFORMATION_EX.java deleted file mode 100644 index 9750d300..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/USB_NODE_CONNECTION_INFORMATION_EX.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -/** - * {@snippet : - * typedef struct _USB_NODE_CONNECTION_INFORMATION_EX USB_NODE_CONNECTION_INFORMATION_EX; - * } - */ -public final class USB_NODE_CONNECTION_INFORMATION_EX extends _USB_NODE_CONNECTION_INFORMATION_EX { - - // Suppresses default constructor, ensuring non-instantiability. - private USB_NODE_CONNECTION_INFORMATION_EX() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_DESCRIPTOR_REQUEST.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_DESCRIPTOR_REQUEST.java deleted file mode 100644 index 38d3f92f..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_DESCRIPTOR_REQUEST.java +++ /dev/null @@ -1,223 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _USB_DESCRIPTOR_REQUEST { - * ULONG ConnectionIndex; - * struct SetupPacket; - * UCHAR Data[0]; - * }; - * } - */ -public class _USB_DESCRIPTOR_REQUEST { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; - } - public static VarHandle ConnectionIndex$VH() { - return constants$0.const$1; - } - /** - * Getter for field: - * {@snippet : - * ULONG ConnectionIndex; - * } - */ - public static int ConnectionIndex$get(MemorySegment seg) { - return (int)constants$0.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG ConnectionIndex; - * } - */ - public static void ConnectionIndex$set(MemorySegment seg, int x) { - constants$0.const$1.set(seg, x); - } - public static int ConnectionIndex$get(MemorySegment seg, long index) { - return (int)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void ConnectionIndex$set(MemorySegment seg, long index, int x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); - } - /** - * {@snippet : - * struct { - * UCHAR bmRequest; - * UCHAR bRequest; - * USHORT wValue; - * USHORT wIndex; - * USHORT wLength; - * }; - * } - */ - public static final class SetupPacket { - - // Suppresses default constructor, ensuring non-instantiability. - private SetupPacket() {} - public static MemoryLayout $LAYOUT() { - return constants$0.const$2; - } - public static VarHandle bmRequest$VH() { - return constants$0.const$3; - } - /** - * Getter for field: - * {@snippet : - * UCHAR bmRequest; - * } - */ - public static byte bmRequest$get(MemorySegment seg) { - return (byte)constants$0.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UCHAR bmRequest; - * } - */ - public static void bmRequest$set(MemorySegment seg, byte x) { - constants$0.const$3.set(seg, x); - } - public static byte bmRequest$get(MemorySegment seg, long index) { - return (byte)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void bmRequest$set(MemorySegment seg, long index, byte x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle bRequest$VH() { - return constants$0.const$4; - } - /** - * Getter for field: - * {@snippet : - * UCHAR bRequest; - * } - */ - public static byte bRequest$get(MemorySegment seg) { - return (byte)constants$0.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UCHAR bRequest; - * } - */ - public static void bRequest$set(MemorySegment seg, byte x) { - constants$0.const$4.set(seg, x); - } - public static byte bRequest$get(MemorySegment seg, long index) { - return (byte)constants$0.const$4.get(seg.asSlice(index*sizeof())); - } - public static void bRequest$set(MemorySegment seg, long index, byte x) { - constants$0.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle wValue$VH() { - return constants$0.const$5; - } - /** - * Getter for field: - * {@snippet : - * USHORT wValue; - * } - */ - public static short wValue$get(MemorySegment seg) { - return (short)constants$0.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * USHORT wValue; - * } - */ - public static void wValue$set(MemorySegment seg, short x) { - constants$0.const$5.set(seg, x); - } - public static short wValue$get(MemorySegment seg, long index) { - return (short)constants$0.const$5.get(seg.asSlice(index*sizeof())); - } - public static void wValue$set(MemorySegment seg, long index, short x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle wIndex$VH() { - return constants$1.const$0; - } - /** - * Getter for field: - * {@snippet : - * USHORT wIndex; - * } - */ - public static short wIndex$get(MemorySegment seg) { - return (short)constants$1.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * USHORT wIndex; - * } - */ - public static void wIndex$set(MemorySegment seg, short x) { - constants$1.const$0.set(seg, x); - } - public static short wIndex$get(MemorySegment seg, long index) { - return (short)constants$1.const$0.get(seg.asSlice(index*sizeof())); - } - public static void wIndex$set(MemorySegment seg, long index, short x) { - constants$1.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle wLength$VH() { - return constants$1.const$1; - } - /** - * Getter for field: - * {@snippet : - * USHORT wLength; - * } - */ - public static short wLength$get(MemorySegment seg) { - return (short)constants$1.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * USHORT wLength; - * } - */ - public static void wLength$set(MemorySegment seg, short x) { - constants$1.const$1.set(seg, x); - } - public static short wLength$get(MemorySegment seg, long index) { - return (short)constants$1.const$1.get(seg.asSlice(index*sizeof())); - } - public static void wLength$set(MemorySegment seg, long index, short x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } - } - - public static MemorySegment SetupPacket$slice(MemorySegment seg) { - return seg.asSlice(4, 8); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_NODE_CONNECTION_INFORMATION_EX.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_NODE_CONNECTION_INFORMATION_EX.java deleted file mode 100644 index 4527cdee..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/_USB_NODE_CONNECTION_INFORMATION_EX.java +++ /dev/null @@ -1,230 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _USB_NODE_CONNECTION_INFORMATION_EX { - * ULONG ConnectionIndex; - * USB_DEVICE_DESCRIPTOR DeviceDescriptor; - * UCHAR CurrentConfigurationValue; - * UCHAR Speed; - * BOOLEAN DeviceIsHub; - * USHORT DeviceAddress; - * ULONG NumberOfOpenPipes; - * USB_CONNECTION_STATUS ConnectionStatus; - * USB_PIPE_INFO PipeList[0]; - * }; - * } - */ -public class _USB_NODE_CONNECTION_INFORMATION_EX { - - public static MemoryLayout $LAYOUT() { - return constants$1.const$2; - } - public static VarHandle ConnectionIndex$VH() { - return constants$1.const$3; - } - /** - * Getter for field: - * {@snippet : - * ULONG ConnectionIndex; - * } - */ - public static int ConnectionIndex$get(MemorySegment seg) { - return (int)constants$1.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG ConnectionIndex; - * } - */ - public static void ConnectionIndex$set(MemorySegment seg, int x) { - constants$1.const$3.set(seg, x); - } - public static int ConnectionIndex$get(MemorySegment seg, long index) { - return (int)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ConnectionIndex$set(MemorySegment seg, long index, int x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment DeviceDescriptor$slice(MemorySegment seg) { - return seg.asSlice(4, 18); - } - public static VarHandle CurrentConfigurationValue$VH() { - return constants$1.const$4; - } - /** - * Getter for field: - * {@snippet : - * UCHAR CurrentConfigurationValue; - * } - */ - public static byte CurrentConfigurationValue$get(MemorySegment seg) { - return (byte)constants$1.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UCHAR CurrentConfigurationValue; - * } - */ - public static void CurrentConfigurationValue$set(MemorySegment seg, byte x) { - constants$1.const$4.set(seg, x); - } - public static byte CurrentConfigurationValue$get(MemorySegment seg, long index) { - return (byte)constants$1.const$4.get(seg.asSlice(index*sizeof())); - } - public static void CurrentConfigurationValue$set(MemorySegment seg, long index, byte x) { - constants$1.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle Speed$VH() { - return constants$1.const$5; - } - /** - * Getter for field: - * {@snippet : - * UCHAR Speed; - * } - */ - public static byte Speed$get(MemorySegment seg) { - return (byte)constants$1.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UCHAR Speed; - * } - */ - public static void Speed$set(MemorySegment seg, byte x) { - constants$1.const$5.set(seg, x); - } - public static byte Speed$get(MemorySegment seg, long index) { - return (byte)constants$1.const$5.get(seg.asSlice(index*sizeof())); - } - public static void Speed$set(MemorySegment seg, long index, byte x) { - constants$1.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle DeviceIsHub$VH() { - return constants$2.const$0; - } - /** - * Getter for field: - * {@snippet : - * BOOLEAN DeviceIsHub; - * } - */ - public static byte DeviceIsHub$get(MemorySegment seg) { - return (byte)constants$2.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * BOOLEAN DeviceIsHub; - * } - */ - public static void DeviceIsHub$set(MemorySegment seg, byte x) { - constants$2.const$0.set(seg, x); - } - public static byte DeviceIsHub$get(MemorySegment seg, long index) { - return (byte)constants$2.const$0.get(seg.asSlice(index*sizeof())); - } - public static void DeviceIsHub$set(MemorySegment seg, long index, byte x) { - constants$2.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle DeviceAddress$VH() { - return constants$2.const$1; - } - /** - * Getter for field: - * {@snippet : - * USHORT DeviceAddress; - * } - */ - public static short DeviceAddress$get(MemorySegment seg) { - return (short)constants$2.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * USHORT DeviceAddress; - * } - */ - public static void DeviceAddress$set(MemorySegment seg, short x) { - constants$2.const$1.set(seg, x); - } - public static short DeviceAddress$get(MemorySegment seg, long index) { - return (short)constants$2.const$1.get(seg.asSlice(index*sizeof())); - } - public static void DeviceAddress$set(MemorySegment seg, long index, short x) { - constants$2.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle NumberOfOpenPipes$VH() { - return constants$2.const$2; - } - /** - * Getter for field: - * {@snippet : - * ULONG NumberOfOpenPipes; - * } - */ - public static int NumberOfOpenPipes$get(MemorySegment seg) { - return (int)constants$2.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * ULONG NumberOfOpenPipes; - * } - */ - public static void NumberOfOpenPipes$set(MemorySegment seg, int x) { - constants$2.const$2.set(seg, x); - } - public static int NumberOfOpenPipes$get(MemorySegment seg, long index) { - return (int)constants$2.const$2.get(seg.asSlice(index*sizeof())); - } - public static void NumberOfOpenPipes$set(MemorySegment seg, long index, int x) { - constants$2.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle ConnectionStatus$VH() { - return constants$2.const$3; - } - /** - * Getter for field: - * {@snippet : - * USB_CONNECTION_STATUS ConnectionStatus; - * } - */ - public static int ConnectionStatus$get(MemorySegment seg) { - return (int)constants$2.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * USB_CONNECTION_STATUS ConnectionStatus; - * } - */ - public static void ConnectionStatus$set(MemorySegment seg, int x) { - constants$2.const$3.set(seg, x); - } - public static int ConnectionStatus$get(MemorySegment seg, long index) { - return (int)constants$2.const$3.get(seg.asSlice(index*sizeof())); - } - public static void ConnectionStatus$set(MemorySegment seg, long index, int x) { - constants$2.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$0.java deleted file mode 100644 index 45923e11..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$0.java +++ /dev/null @@ -1,38 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withByteAlignment(1).withName("ConnectionIndex"), - MemoryLayout.structLayout( - JAVA_BYTE.withName("bmRequest"), - JAVA_BYTE.withName("bRequest"), - JAVA_SHORT.withByteAlignment(1).withName("wValue"), - JAVA_SHORT.withByteAlignment(1).withName("wIndex"), - JAVA_SHORT.withByteAlignment(1).withName("wLength") - ).withName("SetupPacket"), - MemoryLayout.sequenceLayout(0, JAVA_BYTE).withName("Data") - ).withName("_USB_DESCRIPTOR_REQUEST"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("ConnectionIndex")); - static final StructLayout const$2 = MemoryLayout.structLayout( - JAVA_BYTE.withName("bmRequest"), - JAVA_BYTE.withName("bRequest"), - JAVA_SHORT.withByteAlignment(1).withName("wValue"), - JAVA_SHORT.withByteAlignment(1).withName("wIndex"), - JAVA_SHORT.withByteAlignment(1).withName("wLength") - ).withName(""); - static final VarHandle const$3 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("bmRequest")); - static final VarHandle const$4 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("bRequest")); - static final VarHandle const$5 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("wValue")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$1.java deleted file mode 100644 index c6508243..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$1.java +++ /dev/null @@ -1,57 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final VarHandle const$0 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("wIndex")); - static final VarHandle const$1 = constants$0.const$2.varHandle(MemoryLayout.PathElement.groupElement("wLength")); - static final StructLayout const$2 = MemoryLayout.structLayout( - JAVA_INT.withByteAlignment(1).withName("ConnectionIndex"), - MemoryLayout.structLayout( - JAVA_BYTE.withName("bLength"), - JAVA_BYTE.withName("bDescriptorType"), - JAVA_SHORT.withByteAlignment(1).withName("bcdUSB"), - JAVA_BYTE.withName("bDeviceClass"), - JAVA_BYTE.withName("bDeviceSubClass"), - JAVA_BYTE.withName("bDeviceProtocol"), - JAVA_BYTE.withName("bMaxPacketSize0"), - JAVA_SHORT.withByteAlignment(1).withName("idVendor"), - JAVA_SHORT.withByteAlignment(1).withName("idProduct"), - JAVA_SHORT.withByteAlignment(1).withName("bcdDevice"), - JAVA_BYTE.withName("iManufacturer"), - JAVA_BYTE.withName("iProduct"), - JAVA_BYTE.withName("iSerialNumber"), - JAVA_BYTE.withName("bNumConfigurations") - ).withName("DeviceDescriptor"), - JAVA_BYTE.withName("CurrentConfigurationValue"), - JAVA_BYTE.withName("Speed"), - JAVA_BYTE.withName("DeviceIsHub"), - JAVA_SHORT.withByteAlignment(1).withName("DeviceAddress"), - JAVA_INT.withByteAlignment(1).withName("NumberOfOpenPipes"), - JAVA_INT.withByteAlignment(1).withName("ConnectionStatus"), - MemoryLayout.sequenceLayout(0, MemoryLayout.structLayout( - MemoryLayout.structLayout( - JAVA_BYTE.withName("bLength"), - JAVA_BYTE.withName("bDescriptorType"), - JAVA_BYTE.withName("bEndpointAddress"), - JAVA_BYTE.withName("bmAttributes"), - JAVA_SHORT.withByteAlignment(1).withName("wMaxPacketSize"), - JAVA_BYTE.withName("bInterval") - ).withName("EndpointDescriptor"), - JAVA_INT.withByteAlignment(1).withName("ScheduleOffset") - ).withName("_USB_PIPE_INFO")).withName("PipeList") - ).withName("_USB_NODE_CONNECTION_INFORMATION_EX"); - static final VarHandle const$3 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("ConnectionIndex")); - static final VarHandle const$4 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("CurrentConfigurationValue")); - static final VarHandle const$5 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("Speed")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$2.java deleted file mode 100644 index 5e83bb48..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/usbioctl/constants$2.java +++ /dev/null @@ -1,17 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.usbioctl; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final VarHandle const$0 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("DeviceIsHub")); - static final VarHandle const$1 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("DeviceAddress")); - static final VarHandle const$2 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("NumberOfOpenPipes")); - static final VarHandle const$3 = constants$1.const$2.varHandle(MemoryLayout.PathElement.groupElement("ConnectionStatus")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_DEVICEINTERFACE_W.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_DEVICEINTERFACE_W.java deleted file mode 100644 index e13c9de5..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_DEVICEINTERFACE_W.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -/** - * {@snippet : - * typedef struct _DEV_BROADCAST_DEVICEINTERFACE_W DEV_BROADCAST_DEVICEINTERFACE_W; - * } - */ -public final class DEV_BROADCAST_DEVICEINTERFACE_W extends _DEV_BROADCAST_DEVICEINTERFACE_W { - - // Suppresses default constructor, ensuring non-instantiability. - private DEV_BROADCAST_DEVICEINTERFACE_W() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_HDR.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_HDR.java deleted file mode 100644 index 684c0ac3..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/DEV_BROADCAST_HDR.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -/** - * {@snippet : - * typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR; - * } - */ -public final class DEV_BROADCAST_HDR extends _DEV_BROADCAST_HDR { - - // Suppresses default constructor, ensuring non-instantiability. - private DEV_BROADCAST_HDR() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/MSG.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/MSG.java deleted file mode 100644 index 1717dd43..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/MSG.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -/** - * {@snippet : - * typedef struct tagMSG MSG; - * } - */ -public final class MSG extends tagMSG { - - // Suppresses default constructor, ensuring non-instantiability. - private MSG() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/RuntimeHelper.java deleted file mode 100644 index c2ce369c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.user32; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("User32"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/User32.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/User32.java deleted file mode 100644 index 31903e05..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/User32.java +++ /dev/null @@ -1,86 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class User32 { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define WM_DEVICECHANGE 537 - * } - */ - public static int WM_DEVICECHANGE() { - return (int)537L; - } - /** - * {@snippet : - * #define DEVICE_NOTIFY_WINDOW_HANDLE 0 - * } - */ - public static int DEVICE_NOTIFY_WINDOW_HANDLE() { - return (int)0L; - } - /** - * {@snippet : - * #define DBT_DEVICEARRIVAL 32768 - * } - */ - public static int DBT_DEVICEARRIVAL() { - return (int)32768L; - } - /** - * {@snippet : - * #define DBT_DEVICEREMOVECOMPLETE 32772 - * } - */ - public static int DBT_DEVICEREMOVECOMPLETE() { - return (int)32772L; - } - /** - * {@snippet : - * #define DBT_DEVTYP_DEVICEINTERFACE 5 - * } - */ - public static int DBT_DEVTYP_DEVICEINTERFACE() { - return (int)5L; - } - public static MethodHandle DefWindowProcW$MH() { - return RuntimeHelper.requireNonNull(constants$3.const$2,"DefWindowProcW"); - } - /** - * {@snippet : - * LRESULT DefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); - * } - */ - public static long DefWindowProcW(MemorySegment hWnd, int Msg, long wParam, long lParam) { - var mh$ = DefWindowProcW$MH(); - try { - return (long)mh$.invokeExact(hWnd, Msg, wParam, lParam); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - /** - * {@snippet : - * #define HWND_MESSAGE -3 - * } - */ - public static MemorySegment HWND_MESSAGE() { - return constants$4.const$5; - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/WNDCLASSEXW.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/WNDCLASSEXW.java deleted file mode 100644 index aa336e43..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/WNDCLASSEXW.java +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -/** - * {@snippet : - * typedef struct tagWNDCLASSEXW WNDCLASSEXW; - * } - */ -public final class WNDCLASSEXW extends tagWNDCLASSEXW { - - // Suppresses default constructor, ensuring non-instantiability. - private WNDCLASSEXW() {} -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_DEVICEINTERFACE_W.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_DEVICEINTERFACE_W.java deleted file mode 100644 index ff9172ce..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_DEVICEINTERFACE_W.java +++ /dev/null @@ -1,121 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _DEV_BROADCAST_DEVICEINTERFACE_W { - * DWORD dbcc_size; - * DWORD dbcc_devicetype; - * DWORD dbcc_reserved; - * GUID dbcc_classguid; - * wchar_t dbcc_name[1]; - * }; - * } - */ -public class _DEV_BROADCAST_DEVICEINTERFACE_W { - - public static MemoryLayout $LAYOUT() { - return constants$4.const$1; - } - public static VarHandle dbcc_size$VH() { - return constants$4.const$2; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbcc_size; - * } - */ - public static int dbcc_size$get(MemorySegment seg) { - return (int)constants$4.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbcc_size; - * } - */ - public static void dbcc_size$set(MemorySegment seg, int x) { - constants$4.const$2.set(seg, x); - } - public static int dbcc_size$get(MemorySegment seg, long index) { - return (int)constants$4.const$2.get(seg.asSlice(index*sizeof())); - } - public static void dbcc_size$set(MemorySegment seg, long index, int x) { - constants$4.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle dbcc_devicetype$VH() { - return constants$4.const$3; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbcc_devicetype; - * } - */ - public static int dbcc_devicetype$get(MemorySegment seg) { - return (int)constants$4.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbcc_devicetype; - * } - */ - public static void dbcc_devicetype$set(MemorySegment seg, int x) { - constants$4.const$3.set(seg, x); - } - public static int dbcc_devicetype$get(MemorySegment seg, long index) { - return (int)constants$4.const$3.get(seg.asSlice(index*sizeof())); - } - public static void dbcc_devicetype$set(MemorySegment seg, long index, int x) { - constants$4.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle dbcc_reserved$VH() { - return constants$4.const$4; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbcc_reserved; - * } - */ - public static int dbcc_reserved$get(MemorySegment seg) { - return (int)constants$4.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbcc_reserved; - * } - */ - public static void dbcc_reserved$set(MemorySegment seg, int x) { - constants$4.const$4.set(seg, x); - } - public static int dbcc_reserved$get(MemorySegment seg, long index) { - return (int)constants$4.const$4.get(seg.asSlice(index*sizeof())); - } - public static void dbcc_reserved$set(MemorySegment seg, long index, int x) { - constants$4.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment dbcc_classguid$slice(MemorySegment seg) { - return seg.asSlice(12, 16); - } - public static MemorySegment dbcc_name$slice(MemorySegment seg) { - return seg.asSlice(28, 2); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_HDR.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_HDR.java deleted file mode 100644 index 06d1ef76..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/_DEV_BROADCAST_HDR.java +++ /dev/null @@ -1,113 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct _DEV_BROADCAST_HDR { - * DWORD dbch_size; - * DWORD dbch_devicetype; - * DWORD dbch_reserved; - * }; - * } - */ -public class _DEV_BROADCAST_HDR { - - public static MemoryLayout $LAYOUT() { - return constants$3.const$3; - } - public static VarHandle dbch_size$VH() { - return constants$3.const$4; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbch_size; - * } - */ - public static int dbch_size$get(MemorySegment seg) { - return (int)constants$3.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbch_size; - * } - */ - public static void dbch_size$set(MemorySegment seg, int x) { - constants$3.const$4.set(seg, x); - } - public static int dbch_size$get(MemorySegment seg, long index) { - return (int)constants$3.const$4.get(seg.asSlice(index*sizeof())); - } - public static void dbch_size$set(MemorySegment seg, long index, int x) { - constants$3.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle dbch_devicetype$VH() { - return constants$3.const$5; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbch_devicetype; - * } - */ - public static int dbch_devicetype$get(MemorySegment seg) { - return (int)constants$3.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbch_devicetype; - * } - */ - public static void dbch_devicetype$set(MemorySegment seg, int x) { - constants$3.const$5.set(seg, x); - } - public static int dbch_devicetype$get(MemorySegment seg, long index) { - return (int)constants$3.const$5.get(seg.asSlice(index*sizeof())); - } - public static void dbch_devicetype$set(MemorySegment seg, long index, int x) { - constants$3.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle dbch_reserved$VH() { - return constants$4.const$0; - } - /** - * Getter for field: - * {@snippet : - * DWORD dbch_reserved; - * } - */ - public static int dbch_reserved$get(MemorySegment seg) { - return (int)constants$4.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD dbch_reserved; - * } - */ - public static void dbch_reserved$set(MemorySegment seg, int x) { - constants$4.const$0.set(seg, x); - } - public static int dbch_reserved$get(MemorySegment seg, long index) { - return (int)constants$4.const$0.get(seg.asSlice(index*sizeof())); - } - public static void dbch_reserved$set(MemorySegment seg, long index, int x) { - constants$4.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$0.java deleted file mode 100644 index c4377aae..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$0.java +++ /dev/null @@ -1,35 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final StructLayout const$0 = MemoryLayout.structLayout( - JAVA_INT.withName("cbSize"), - JAVA_INT.withName("style"), - RuntimeHelper.POINTER.withName("lpfnWndProc"), - JAVA_INT.withName("cbClsExtra"), - JAVA_INT.withName("cbWndExtra"), - RuntimeHelper.POINTER.withName("hInstance"), - RuntimeHelper.POINTER.withName("hIcon"), - RuntimeHelper.POINTER.withName("hCursor"), - RuntimeHelper.POINTER.withName("hbrBackground"), - RuntimeHelper.POINTER.withName("lpszMenuName"), - RuntimeHelper.POINTER.withName("lpszClassName"), - RuntimeHelper.POINTER.withName("hIconSm") - ).withName("tagWNDCLASSEXW"); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("cbSize")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("style")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("lpfnWndProc")); - static final VarHandle const$4 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("cbClsExtra")); - static final VarHandle const$5 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("cbWndExtra")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$1.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$1.java deleted file mode 100644 index 1836e3c4..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$1.java +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.MemoryLayout; -import java.lang.invoke.VarHandle; -final class constants$1 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$1() {} - static final VarHandle const$0 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("hInstance")); - static final VarHandle const$1 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("hIcon")); - static final VarHandle const$2 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("hCursor")); - static final VarHandle const$3 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("hbrBackground")); - static final VarHandle const$4 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("lpszMenuName")); - static final VarHandle const$5 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("lpszClassName")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$2.java deleted file mode 100644 index 7fba5be6..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$2.java +++ /dev/null @@ -1,35 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_LONG; -final class constants$2 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$2() {} - static final VarHandle const$0 = constants$0.const$0.varHandle(MemoryLayout.PathElement.groupElement("hIconSm")); - static final StructLayout const$1 = MemoryLayout.structLayout( - RuntimeHelper.POINTER.withName("hwnd"), - JAVA_INT.withName("message"), - MemoryLayout.paddingLayout(4), - JAVA_LONG.withName("wParam"), - JAVA_LONG.withName("lParam"), - JAVA_INT.withName("time"), - MemoryLayout.structLayout( - JAVA_INT.withName("x"), - JAVA_INT.withName("y") - ).withName("pt"), - MemoryLayout.paddingLayout(4) - ).withName("tagMSG"); - static final VarHandle const$2 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("hwnd")); - static final VarHandle const$3 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("message")); - static final VarHandle const$4 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("wParam")); - static final VarHandle const$5 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("lParam")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$3.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$3.java deleted file mode 100644 index 1ab09470..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$3.java +++ /dev/null @@ -1,37 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.StructLayout; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_LONG; -final class constants$3 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$3() {} - static final VarHandle const$0 = constants$2.const$1.varHandle(MemoryLayout.PathElement.groupElement("time")); - static final FunctionDescriptor const$1 = FunctionDescriptor.of(JAVA_LONG, - RuntimeHelper.POINTER, - JAVA_INT, - JAVA_LONG, - JAVA_LONG - ); - static final MethodHandle const$2 = RuntimeHelper.downcallHandle( - "DefWindowProcW", - constants$3.const$1 - ); - static final StructLayout const$3 = MemoryLayout.structLayout( - JAVA_INT.withName("dbch_size"), - JAVA_INT.withName("dbch_devicetype"), - JAVA_INT.withName("dbch_reserved") - ).withName("_DEV_BROADCAST_HDR"); - static final VarHandle const$4 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("dbch_size")); - static final VarHandle const$5 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("dbch_devicetype")); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$4.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$4.java deleted file mode 100644 index 441a40cc..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/constants$4.java +++ /dev/null @@ -1,35 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.StructLayout; -import java.lang.invoke.VarHandle; - -import static java.lang.foreign.ValueLayout.*; -final class constants$4 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$4() {} - static final VarHandle const$0 = constants$3.const$3.varHandle(MemoryLayout.PathElement.groupElement("dbch_reserved")); - static final StructLayout const$1 = MemoryLayout.structLayout( - JAVA_INT.withName("dbcc_size"), - JAVA_INT.withName("dbcc_devicetype"), - JAVA_INT.withName("dbcc_reserved"), - MemoryLayout.structLayout( - JAVA_INT.withName("Data1"), - JAVA_SHORT.withName("Data2"), - JAVA_SHORT.withName("Data3"), - MemoryLayout.sequenceLayout(8, JAVA_BYTE).withName("Data4") - ).withName("dbcc_classguid"), - MemoryLayout.sequenceLayout(1, JAVA_SHORT).withName("dbcc_name"), - MemoryLayout.paddingLayout(2) - ).withName("_DEV_BROADCAST_DEVICEINTERFACE_W"); - static final VarHandle const$2 = constants$4.const$1.varHandle(MemoryLayout.PathElement.groupElement("dbcc_size")); - static final VarHandle const$3 = constants$4.const$1.varHandle(MemoryLayout.PathElement.groupElement("dbcc_devicetype")); - static final VarHandle const$4 = constants$4.const$1.varHandle(MemoryLayout.PathElement.groupElement("dbcc_reserved")); - static final MemorySegment const$5 = MemorySegment.ofAddress(-3L); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagMSG.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagMSG.java deleted file mode 100644 index 98724ca8..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagMSG.java +++ /dev/null @@ -1,173 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct tagMSG { - * HWND hwnd; - * UINT message; - * WPARAM wParam; - * LPARAM lParam; - * DWORD time; - * POINT pt; - * }; - * } - */ -public class tagMSG { - - public static MemoryLayout $LAYOUT() { - return constants$2.const$1; - } - public static VarHandle hwnd$VH() { - return constants$2.const$2; - } - /** - * Getter for field: - * {@snippet : - * HWND hwnd; - * } - */ - public static MemorySegment hwnd$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$2.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HWND hwnd; - * } - */ - public static void hwnd$set(MemorySegment seg, MemorySegment x) { - constants$2.const$2.set(seg, x); - } - public static MemorySegment hwnd$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$2.const$2.get(seg.asSlice(index*sizeof())); - } - public static void hwnd$set(MemorySegment seg, long index, MemorySegment x) { - constants$2.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle message$VH() { - return constants$2.const$3; - } - /** - * Getter for field: - * {@snippet : - * UINT message; - * } - */ - public static int message$get(MemorySegment seg) { - return (int)constants$2.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UINT message; - * } - */ - public static void message$set(MemorySegment seg, int x) { - constants$2.const$3.set(seg, x); - } - public static int message$get(MemorySegment seg, long index) { - return (int)constants$2.const$3.get(seg.asSlice(index*sizeof())); - } - public static void message$set(MemorySegment seg, long index, int x) { - constants$2.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle wParam$VH() { - return constants$2.const$4; - } - /** - * Getter for field: - * {@snippet : - * WPARAM wParam; - * } - */ - public static long wParam$get(MemorySegment seg) { - return (long)constants$2.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * WPARAM wParam; - * } - */ - public static void wParam$set(MemorySegment seg, long x) { - constants$2.const$4.set(seg, x); - } - public static long wParam$get(MemorySegment seg, long index) { - return (long)constants$2.const$4.get(seg.asSlice(index*sizeof())); - } - public static void wParam$set(MemorySegment seg, long index, long x) { - constants$2.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle lParam$VH() { - return constants$2.const$5; - } - /** - * Getter for field: - * {@snippet : - * LPARAM lParam; - * } - */ - public static long lParam$get(MemorySegment seg) { - return (long)constants$2.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * LPARAM lParam; - * } - */ - public static void lParam$set(MemorySegment seg, long x) { - constants$2.const$5.set(seg, x); - } - public static long lParam$get(MemorySegment seg, long index) { - return (long)constants$2.const$5.get(seg.asSlice(index*sizeof())); - } - public static void lParam$set(MemorySegment seg, long index, long x) { - constants$2.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle time$VH() { - return constants$3.const$0; - } - /** - * Getter for field: - * {@snippet : - * DWORD time; - * } - */ - public static int time$get(MemorySegment seg) { - return (int)constants$3.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * DWORD time; - * } - */ - public static void time$set(MemorySegment seg, int x) { - constants$3.const$0.set(seg, x); - } - public static int time$get(MemorySegment seg, long index) { - return (int)constants$3.const$0.get(seg.asSlice(index*sizeof())); - } - public static void time$set(MemorySegment seg, long index, int x) { - constants$3.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static MemorySegment pt$slice(MemorySegment seg) { - return seg.asSlice(36, 8); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagWNDCLASSEXW.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagWNDCLASSEXW.java deleted file mode 100644 index 6f6c3346..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/user32/tagWNDCLASSEXW.java +++ /dev/null @@ -1,365 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.user32; - -import java.lang.foreign.Arena; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; -import java.lang.invoke.VarHandle; -/** - * {@snippet : - * struct tagWNDCLASSEXW { - * UINT cbSize; - * UINT style; - * WNDPROC lpfnWndProc; - * int cbClsExtra; - * int cbWndExtra; - * HINSTANCE hInstance; - * HICON hIcon; - * HCURSOR hCursor; - * HBRUSH hbrBackground; - * LPCWSTR lpszMenuName; - * LPCWSTR lpszClassName; - * HICON hIconSm; - * }; - * } - */ -public class tagWNDCLASSEXW { - - public static MemoryLayout $LAYOUT() { - return constants$0.const$0; - } - public static VarHandle cbSize$VH() { - return constants$0.const$1; - } - /** - * Getter for field: - * {@snippet : - * UINT cbSize; - * } - */ - public static int cbSize$get(MemorySegment seg) { - return (int)constants$0.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UINT cbSize; - * } - */ - public static void cbSize$set(MemorySegment seg, int x) { - constants$0.const$1.set(seg, x); - } - public static int cbSize$get(MemorySegment seg, long index) { - return (int)constants$0.const$1.get(seg.asSlice(index*sizeof())); - } - public static void cbSize$set(MemorySegment seg, long index, int x) { - constants$0.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle style$VH() { - return constants$0.const$2; - } - /** - * Getter for field: - * {@snippet : - * UINT style; - * } - */ - public static int style$get(MemorySegment seg) { - return (int)constants$0.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * UINT style; - * } - */ - public static void style$set(MemorySegment seg, int x) { - constants$0.const$2.set(seg, x); - } - public static int style$get(MemorySegment seg, long index) { - return (int)constants$0.const$2.get(seg.asSlice(index*sizeof())); - } - public static void style$set(MemorySegment seg, long index, int x) { - constants$0.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle lpfnWndProc$VH() { - return constants$0.const$3; - } - /** - * Getter for field: - * {@snippet : - * WNDPROC lpfnWndProc; - * } - */ - public static MemorySegment lpfnWndProc$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$0.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * WNDPROC lpfnWndProc; - * } - */ - public static void lpfnWndProc$set(MemorySegment seg, MemorySegment x) { - constants$0.const$3.set(seg, x); - } - public static MemorySegment lpfnWndProc$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$0.const$3.get(seg.asSlice(index*sizeof())); - } - public static void lpfnWndProc$set(MemorySegment seg, long index, MemorySegment x) { - constants$0.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle cbClsExtra$VH() { - return constants$0.const$4; - } - /** - * Getter for field: - * {@snippet : - * int cbClsExtra; - * } - */ - public static int cbClsExtra$get(MemorySegment seg) { - return (int)constants$0.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * int cbClsExtra; - * } - */ - public static void cbClsExtra$set(MemorySegment seg, int x) { - constants$0.const$4.set(seg, x); - } - public static int cbClsExtra$get(MemorySegment seg, long index) { - return (int)constants$0.const$4.get(seg.asSlice(index*sizeof())); - } - public static void cbClsExtra$set(MemorySegment seg, long index, int x) { - constants$0.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle cbWndExtra$VH() { - return constants$0.const$5; - } - /** - * Getter for field: - * {@snippet : - * int cbWndExtra; - * } - */ - public static int cbWndExtra$get(MemorySegment seg) { - return (int)constants$0.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * int cbWndExtra; - * } - */ - public static void cbWndExtra$set(MemorySegment seg, int x) { - constants$0.const$5.set(seg, x); - } - public static int cbWndExtra$get(MemorySegment seg, long index) { - return (int)constants$0.const$5.get(seg.asSlice(index*sizeof())); - } - public static void cbWndExtra$set(MemorySegment seg, long index, int x) { - constants$0.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hInstance$VH() { - return constants$1.const$0; - } - /** - * Getter for field: - * {@snippet : - * HINSTANCE hInstance; - * } - */ - public static MemorySegment hInstance$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HINSTANCE hInstance; - * } - */ - public static void hInstance$set(MemorySegment seg, MemorySegment x) { - constants$1.const$0.set(seg, x); - } - public static MemorySegment hInstance$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$0.get(seg.asSlice(index*sizeof())); - } - public static void hInstance$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hIcon$VH() { - return constants$1.const$1; - } - /** - * Getter for field: - * {@snippet : - * HICON hIcon; - * } - */ - public static MemorySegment hIcon$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$1.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HICON hIcon; - * } - */ - public static void hIcon$set(MemorySegment seg, MemorySegment x) { - constants$1.const$1.set(seg, x); - } - public static MemorySegment hIcon$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$1.get(seg.asSlice(index*sizeof())); - } - public static void hIcon$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$1.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hCursor$VH() { - return constants$1.const$2; - } - /** - * Getter for field: - * {@snippet : - * HCURSOR hCursor; - * } - */ - public static MemorySegment hCursor$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$2.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HCURSOR hCursor; - * } - */ - public static void hCursor$set(MemorySegment seg, MemorySegment x) { - constants$1.const$2.set(seg, x); - } - public static MemorySegment hCursor$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$2.get(seg.asSlice(index*sizeof())); - } - public static void hCursor$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$2.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hbrBackground$VH() { - return constants$1.const$3; - } - /** - * Getter for field: - * {@snippet : - * HBRUSH hbrBackground; - * } - */ - public static MemorySegment hbrBackground$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$3.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HBRUSH hbrBackground; - * } - */ - public static void hbrBackground$set(MemorySegment seg, MemorySegment x) { - constants$1.const$3.set(seg, x); - } - public static MemorySegment hbrBackground$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$3.get(seg.asSlice(index*sizeof())); - } - public static void hbrBackground$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$3.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle lpszMenuName$VH() { - return constants$1.const$4; - } - /** - * Getter for field: - * {@snippet : - * LPCWSTR lpszMenuName; - * } - */ - public static MemorySegment lpszMenuName$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$4.get(seg); - } - /** - * Setter for field: - * {@snippet : - * LPCWSTR lpszMenuName; - * } - */ - public static void lpszMenuName$set(MemorySegment seg, MemorySegment x) { - constants$1.const$4.set(seg, x); - } - public static MemorySegment lpszMenuName$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$4.get(seg.asSlice(index*sizeof())); - } - public static void lpszMenuName$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$4.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle lpszClassName$VH() { - return constants$1.const$5; - } - /** - * Getter for field: - * {@snippet : - * LPCWSTR lpszClassName; - * } - */ - public static MemorySegment lpszClassName$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$1.const$5.get(seg); - } - /** - * Setter for field: - * {@snippet : - * LPCWSTR lpszClassName; - * } - */ - public static void lpszClassName$set(MemorySegment seg, MemorySegment x) { - constants$1.const$5.set(seg, x); - } - public static MemorySegment lpszClassName$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$1.const$5.get(seg.asSlice(index*sizeof())); - } - public static void lpszClassName$set(MemorySegment seg, long index, MemorySegment x) { - constants$1.const$5.set(seg.asSlice(index*sizeof()), x); - } - public static VarHandle hIconSm$VH() { - return constants$2.const$0; - } - /** - * Getter for field: - * {@snippet : - * HICON hIconSm; - * } - */ - public static MemorySegment hIconSm$get(MemorySegment seg) { - return (java.lang.foreign.MemorySegment)constants$2.const$0.get(seg); - } - /** - * Setter for field: - * {@snippet : - * HICON hIconSm; - * } - */ - public static void hIconSm$set(MemorySegment seg, MemorySegment x) { - constants$2.const$0.set(seg, x); - } - public static MemorySegment hIconSm$get(MemorySegment seg, long index) { - return (java.lang.foreign.MemorySegment)constants$2.const$0.get(seg.asSlice(index*sizeof())); - } - public static void hIconSm$set(MemorySegment seg, long index, MemorySegment x) { - constants$2.const$0.set(seg.asSlice(index*sizeof()), x); - } - public static long sizeof() { return $LAYOUT().byteSize(); } - public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } - public static MemorySegment allocateArray(long len, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); - } - public static MemorySegment ofAddress(MemorySegment addr, Arena scope) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, scope); } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/RuntimeHelper.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/RuntimeHelper.java deleted file mode 100644 index c9ab3d52..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/RuntimeHelper.java +++ /dev/null @@ -1,227 +0,0 @@ -package net.codecrete.usb.windows.gen.winusb; -// Generated by jextract - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import static java.lang.foreign.ValueLayout.*; - -final class RuntimeHelper { - - private static final Linker LINKER = Linker.nativeLinker(); - private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); - private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); - private static final SymbolLookup SYMBOL_LOOKUP; - private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; - static final AddressLayout POINTER = ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE)); - - final static SegmentAllocator CONSTANT_ALLOCATOR = - (size, align) -> Arena.ofAuto().allocate(size, align); - - static { - System.loadLibrary("Winusb"); - SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name)); - } - - // Suppresses default constructor, ensuring non-instantiability. - private RuntimeHelper() {} - - static T requireNonNull(T obj, String symbolName) { - if (obj == null) { - throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); - } - return obj; - } - - static MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { - return SYMBOL_LOOKUP.find(name) - .map(s -> s.reinterpret(layout.byteSize())) - .orElse(null); - } - - static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> LINKER.downcallHandle(addr, fdesc)). - orElse(null); - } - - static MethodHandle downcallHandle(FunctionDescriptor fdesc) { - return LINKER.downcallHandle(fdesc); - } - - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { - return SYMBOL_LOOKUP.find(name). - map(addr -> VarargsInvoker.make(addr, fdesc)). - orElse(null); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { - try { - fiHandle = fiHandle.bindTo(z); - return LINKER.upcallStub(fiHandle, fdesc, scope); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) { - return addr.reinterpret(numElements * layout.byteSize(), arena, null); - } - - // Internals only below this point - - private static final class VarargsInvoker { - private static final MethodHandle INVOKE_MH; - private final MemorySegment symbol; - private final FunctionDescriptor function; - - private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { - this.symbol = symbol; - this.function = function; - } - - static { - try { - INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { - VarargsInvoker invoker = new VarargsInvoker(symbol, function); - MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); - MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); - for (MemoryLayout layout : function.argumentLayouts()) { - mtype = mtype.appendParameterTypes(carrier(layout, false)); - } - mtype = mtype.appendParameterTypes(Object[].class); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); - } else { - handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); - } - return handle.asType(mtype); - } - - static Class carrier(MemoryLayout layout, boolean ret) { - if (layout instanceof ValueLayout valueLayout) { - return valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new AssertionError("Cannot get here!"); - } - } - - private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { - // one trailing Object[] - int nNamedArgs = function.argumentLayouts().size(); - assert(args.length == nNamedArgs + 1); - // The last argument is the array of vararg collector - Object[] unnamedArgs = (Object[]) args[args.length - 1]; - - int argsCount = nNamedArgs + unnamedArgs.length; - Class[] argTypes = new Class[argsCount]; - MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; - - int pos = 0; - for (pos = 0; pos < nNamedArgs; pos++) { - argLayouts[pos] = function.argumentLayouts().get(pos); - } - - assert pos == nNamedArgs; - for (Object o: unnamedArgs) { - argLayouts[pos] = variadicLayout(normalize(o.getClass())); - pos++; - } - assert pos == argsCount; - - FunctionDescriptor f = (function.returnLayout().isEmpty()) ? - FunctionDescriptor.ofVoid(argLayouts) : - FunctionDescriptor.of(function.returnLayout().get(), argLayouts); - MethodHandle mh = LINKER.downcallHandle(symbol, f); - boolean needsAllocator = function.returnLayout().isPresent() && - function.returnLayout().get() instanceof GroupLayout; - if (needsAllocator) { - mh = mh.bindTo(allocator); - } - // flatten argument list so that it can be passed to an asSpreader MH - Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; - System.arraycopy(args, 0, allArgs, 0, nNamedArgs); - System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); - - return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); - } - - private static Class unboxIfNeeded(Class clazz) { - if (clazz == Boolean.class) { - return boolean.class; - } else if (clazz == Void.class) { - return void.class; - } else if (clazz == Byte.class) { - return byte.class; - } else if (clazz == Character.class) { - return char.class; - } else if (clazz == Short.class) { - return short.class; - } else if (clazz == Integer.class) { - return int.class; - } else if (clazz == Long.class) { - return long.class; - } else if (clazz == Float.class) { - return float.class; - } else if (clazz == Double.class) { - return double.class; - } else { - return clazz; - } - } - - private Class promote(Class c) { - if (c == byte.class || c == char.class || c == short.class || c == int.class) { - return long.class; - } else if (c == float.class) { - return double.class; - } else { - return c; - } - } - - private Class normalize(Class c) { - c = unboxIfNeeded(c); - if (c.isPrimitive()) { - return promote(c); - } - if (c == MemorySegment.class) { - return MemorySegment.class; - } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); - } - - private MemoryLayout variadicLayout(Class c) { - if (c == long.class) { - return JAVA_LONG; - } else if (c == double.class) { - return JAVA_DOUBLE; - } else if (c == MemorySegment.class) { - return ADDRESS; - } else { - throw new IllegalArgumentException("Unhandled variadic argument class: " + c); - } - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/WinUSB.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/WinUSB.java deleted file mode 100644 index a35ff11d..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/WinUSB.java +++ /dev/null @@ -1,54 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.winusb; - -import java.lang.foreign.AddressLayout; -import java.lang.foreign.MemorySegment; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; -public class WinUSB { - - public static final OfByte C_CHAR = JAVA_BYTE; - public static final OfShort C_SHORT = JAVA_SHORT; - public static final OfInt C_INT = JAVA_INT; - public static final OfInt C_LONG = JAVA_INT; - public static final OfLong C_LONG_LONG = JAVA_LONG; - public static final OfFloat C_FLOAT = JAVA_FLOAT; - public static final OfDouble C_DOUBLE = JAVA_DOUBLE; - public static final AddressLayout C_POINTER = RuntimeHelper.POINTER; - /** - * {@snippet : - * #define PIPE_TRANSFER_TIMEOUT 3 - * } - */ - public static int PIPE_TRANSFER_TIMEOUT() { - return (int)3L; - } - /** - * {@snippet : - * #define RAW_IO 7 - * } - */ - public static int RAW_IO() { - return (int)7L; - } - public static MethodHandle WinUsb_Free$MH() { - return RuntimeHelper.requireNonNull(constants$0.const$1,"WinUsb_Free"); - } - /** - * {@snippet : - * BOOL WinUsb_Free(WINUSB_INTERFACE_HANDLE InterfaceHandle); - * } - */ - public static int WinUsb_Free(MemorySegment InterfaceHandle) { - var mh$ = WinUsb_Free$MH(); - try { - return (int)mh$.invokeExact(InterfaceHandle); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/constants$0.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/constants$0.java deleted file mode 100644 index 90f3902c..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/gen/winusb/constants$0.java +++ /dev/null @@ -1,22 +0,0 @@ -// Generated by jextract - -package net.codecrete.usb.windows.gen.winusb; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.JAVA_INT; -final class constants$0 { - - // Suppresses default constructor, ensuring non-instantiability. - private constants$0() {} - static final FunctionDescriptor const$0 = FunctionDescriptor.of(JAVA_INT, - RuntimeHelper.POINTER - ); - static final MethodHandle const$1 = RuntimeHelper.downcallHandle( - "WinUsb_Free", - constants$0.const$0 - ); -} - - diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/Kernel32B.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/Kernel32B.java deleted file mode 100644 index 4de451fa..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/Kernel32B.java +++ /dev/null @@ -1,108 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -package net.codecrete.usb.windows.winsdk; - -import net.codecrete.usb.windows.Win; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; - -/** - * Native function calls for Kernel32. - *

- * This code is manually created to include the additional parameters for capturing - * {@code GetLastError()} until jextract catches up and can generate the corresponding code. - *

- */ -@SuppressWarnings({"OptionalGetWithoutIsPresent", "java:S100", "java:S107", "java:S117"}) -public class Kernel32B { - static { - System.loadLibrary("Kernel32"); - } - - private Kernel32B() { - } - - private static final Linker LINKER = Linker.nativeLinker(); - private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); - - - private static final FunctionDescriptor CreateFileW$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_INT, - JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, ADDRESS); - - private static final MethodHandle CreateFileW$MH = LINKER.downcallHandle(LOOKUP.find("CreateFileW").get(), - CreateFileW$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment CreateFileW(MemorySegment lpFileName, int dwDesiredAccess, int dwShareMode, - MemorySegment lpSecurityAttributes, int dwCreationDisposition, - int dwFlagsAndAttributes, MemorySegment hTemplateFile, - MemorySegment lastErrorState) { - try { - return (MemorySegment) CreateFileW$MH.invokeExact(lastErrorState, lpFileName, dwDesiredAccess, - dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor DeviceIoControl$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, - ADDRESS, JAVA_INT, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle DeviceIoControl$MH = LINKER.downcallHandle(LOOKUP.find("DeviceIoControl").get() - , DeviceIoControl$FUNC, Win.LAST_ERROR_STATE); - - public static int DeviceIoControl(MemorySegment hDevice, int dwIoControlCode, MemorySegment lpInBuffer, - int nInBufferSize, MemorySegment lpOutBuffer, int nOutBufferSize, - MemorySegment lpBytesReturned, MemorySegment lpOverlapped, - MemorySegment lastErrorState) { - try { - return (int) DeviceIoControl$MH.invokeExact(lastErrorState, hDevice, dwIoControlCode, lpInBuffer, - nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor GetQueuedCompletionStatus$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - ADDRESS, ADDRESS, ADDRESS, JAVA_INT); - - private static final MethodHandle GetQueuedCompletionStatus$MH = LINKER.downcallHandle(LOOKUP.find( - "GetQueuedCompletionStatus").get(), GetQueuedCompletionStatus$FUNC, Win.LAST_ERROR_STATE); - - public static int GetQueuedCompletionStatus(MemorySegment CompletionPort, - MemorySegment lpNumberOfBytesTransferred, - MemorySegment lpCompletionKey, MemorySegment lpOverlapped, - int dwMilliseconds, MemorySegment lastErrorState) { - try { - return (int) GetQueuedCompletionStatus$MH.invokeExact(lastErrorState, CompletionPort, - lpNumberOfBytesTransferred, lpCompletionKey, lpOverlapped, dwMilliseconds); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor CreateIoCompletionPort$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS, - ADDRESS, JAVA_LONG, JAVA_INT); - - private static final MethodHandle CreateIoCompletionPort$MH = LINKER.downcallHandle(LOOKUP.find( - "CreateIoCompletionPort").get(), CreateIoCompletionPort$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment CreateIoCompletionPort(MemorySegment FileHandle, MemorySegment ExistingCompletionPort - , long CompletionKey, int NumberOfConcurrentThreads, MemorySegment lastErrorState) { - try { - return (MemorySegment) CreateIoCompletionPort$MH.invokeExact(lastErrorState, FileHandle, - ExistingCompletionPort, CompletionKey, NumberOfConcurrentThreads); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/SetupAPI2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/SetupAPI2.java deleted file mode 100644 index ff9d15f8..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/SetupAPI2.java +++ /dev/null @@ -1,191 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -package net.codecrete.usb.windows.winsdk; - -import net.codecrete.usb.windows.Win; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_INT; - -/** - * Native function calls for SetupAPI. - *

- * This code is manually created to include the additional parameters for capturing - * {@code GetLastError()} until jextract catches up and can generate the corresponding code. - *

- */ -@SuppressWarnings({"OptionalGetWithoutIsPresent", "java:S100", "java:S107", "java:S117"}) -public class SetupAPI2 { - private SetupAPI2() { - } - - static { - System.loadLibrary("SetupAPI"); - } - - private static final Linker LINKER = Linker.nativeLinker(); - private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); - - private static final FunctionDescriptor SetupDiGetDevicePropertyW$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - ADDRESS, ADDRESS, ADDRESS, ADDRESS, JAVA_INT, ADDRESS, JAVA_INT); - - private static final MethodHandle SetupDiGetDevicePropertyW$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiGetDevicePropertyW").get(), SetupDiGetDevicePropertyW$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiGetDevicePropertyW(MemorySegment DeviceInfoSet, MemorySegment DeviceInfoData, - MemorySegment PropertyKey, MemorySegment PropertyType, - MemorySegment PropertyBuffer, int PropertyBufferSize, - MemorySegment RequiredSize, int Flags, MemorySegment lastErrorState) { - try { - return (int) SetupDiGetDevicePropertyW$MH.invokeExact(lastErrorState, DeviceInfoSet, DeviceInfoData, - PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiEnumDeviceInfo$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - JAVA_INT, ADDRESS); - - private static final MethodHandle SetupDiEnumDeviceInfo$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiEnumDeviceInfo").get(), SetupDiEnumDeviceInfo$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiEnumDeviceInfo(MemorySegment DeviceInfoSet, int MemberIndex, - MemorySegment DeviceInfoData, MemorySegment lastErrorState) { - try { - return (int) SetupDiEnumDeviceInfo$MH.invokeExact(lastErrorState, DeviceInfoSet, MemberIndex, - DeviceInfoData); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiOpenDevRegKey$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS, - ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); - - private static final MethodHandle SetupDiOpenDevRegKey$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiOpenDevRegKey").get(), SetupDiOpenDevRegKey$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment SetupDiOpenDevRegKey(MemorySegment DeviceInfoSet, MemorySegment DeviceInfoData, - int Scope, int HwProfile, int KeyType, int samDesired, - MemorySegment lastErrorState) { - try { - return (MemorySegment) SetupDiOpenDevRegKey$MH.invokeExact(lastErrorState, DeviceInfoSet, DeviceInfoData, - Scope, HwProfile, KeyType, samDesired); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiGetClassDevsW$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS, - ADDRESS, ADDRESS, JAVA_INT); - - private static final MethodHandle SetupDiGetClassDevsW$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiGetClassDevsW").get(), SetupDiGetClassDevsW$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment SetupDiGetClassDevsW(MemorySegment ClassGuid, MemorySegment Enumerator, - MemorySegment hwndParent, int Flags, - MemorySegment lastErrorState) { - try { - return (MemorySegment) SetupDiGetClassDevsW$MH.invokeExact(lastErrorState, ClassGuid, Enumerator, - hwndParent, Flags); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiEnumDeviceInterfaces$FUNC = FunctionDescriptor.of(JAVA_INT, - ADDRESS, ADDRESS, ADDRESS, JAVA_INT, ADDRESS); - - private static final MethodHandle SetupDiEnumDeviceInterfaces$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiEnumDeviceInterfaces").get(), SetupDiEnumDeviceInterfaces$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiEnumDeviceInterfaces(MemorySegment DeviceInfoSet, MemorySegment DeviceInfoData, - MemorySegment InterfaceClassGuid, int MemberIndex, - MemorySegment DeviceInterfaceData, MemorySegment lastErrorState) { - try { - return (int) SetupDiEnumDeviceInterfaces$MH.invokeExact(lastErrorState, DeviceInfoSet, DeviceInfoData, - InterfaceClassGuid, MemberIndex, DeviceInterfaceData); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiGetDeviceInterfaceDetailW$FUNC = FunctionDescriptor.of(JAVA_INT, - ADDRESS, ADDRESS, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle SetupDiGetDeviceInterfaceDetailW$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiGetDeviceInterfaceDetailW").get(), SetupDiGetDeviceInterfaceDetailW$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiGetDeviceInterfaceDetailW(MemorySegment DeviceInfoSet, MemorySegment DeviceInterfaceData - , MemorySegment DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, MemorySegment RequiredSize, - MemorySegment DeviceInfoData, MemorySegment lastErrorState) { - try { - return (int) SetupDiGetDeviceInterfaceDetailW$MH.invokeExact(lastErrorState, DeviceInfoSet, - DeviceInterfaceData, DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, RequiredSize, - DeviceInfoData); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiCreateDeviceInfoList$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS - , ADDRESS); - - private static final MethodHandle SetupDiCreateDeviceInfoList$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiCreateDeviceInfoList").get(), SetupDiCreateDeviceInfoList$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment SetupDiCreateDeviceInfoList(MemorySegment ClassGuid, MemorySegment hwndParent, - MemorySegment lastErrorState) { - try { - return (MemorySegment) SetupDiCreateDeviceInfoList$MH.invokeExact(lastErrorState, ClassGuid, hwndParent); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiOpenDeviceInfoW$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - ADDRESS, ADDRESS, JAVA_INT, ADDRESS); - - private static final MethodHandle SetupDiOpenDeviceInfoW$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiOpenDeviceInfoW").get(), SetupDiOpenDeviceInfoW$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiOpenDeviceInfoW(MemorySegment DeviceInfoSet, MemorySegment DeviceInstanceId, - MemorySegment hwndParent, int OpenFlags, MemorySegment DeviceInfoData, - MemorySegment lastErrorState) { - try { - return (int) SetupDiOpenDeviceInfoW$MH.invokeExact(lastErrorState, DeviceInfoSet, DeviceInstanceId, - hwndParent, OpenFlags, DeviceInfoData); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor SetupDiOpenDeviceInterfaceW$FUNC = FunctionDescriptor.of(JAVA_INT, - ADDRESS, ADDRESS, JAVA_INT, ADDRESS); - - private static final MethodHandle SetupDiOpenDeviceInterfaceW$MH = LINKER.downcallHandle(LOOKUP.find( - "SetupDiOpenDeviceInterfaceW").get(), SetupDiOpenDeviceInterfaceW$FUNC, Win.LAST_ERROR_STATE); - - public static int SetupDiOpenDeviceInterfaceW(MemorySegment DeviceInfoSet, MemorySegment DevicePath, - int OpenFlags, MemorySegment DeviceInterfaceData, - MemorySegment lastErrorState) { - try { - return (int) SetupDiOpenDeviceInterfaceW$MH.invokeExact(lastErrorState, DeviceInfoSet, DevicePath, - OpenFlags, DeviceInterfaceData); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/User32B.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/User32B.java deleted file mode 100644 index 05caa2f2..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/User32B.java +++ /dev/null @@ -1,102 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -package net.codecrete.usb.windows.winsdk; - -import net.codecrete.usb.windows.Win; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; - -/** - * Native function calls for User32. - *

- * This code is manually created to include the additional parameters for capturing - * {@code GetLastError()} until jextract catches up and can generate the corresponding code. - *

- */ -@SuppressWarnings({"OptionalGetWithoutIsPresent", "java:S100", "java:S107", "java:S117"}) -public class User32B { - - private User32B() { - } - - static { - System.loadLibrary("User32"); - } - - private static final Linker LINKER = Linker.nativeLinker(); - private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); - - private static final FunctionDescriptor RegisterClassExW$FUNC = FunctionDescriptor.of(JAVA_SHORT, ADDRESS); - - private static final MethodHandle RegisterClassExW$MH = - LINKER.downcallHandle(LOOKUP.find("RegisterClassExW").get(), RegisterClassExW$FUNC, Win.LAST_ERROR_STATE); - - public static short RegisterClassExW(MemorySegment unnamedParam1, MemorySegment lastErrorState) { - try { - return (short) RegisterClassExW$MH.invokeExact(lastErrorState, unnamedParam1); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor CreateWindowExW$FUNC = FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS, - ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS, ADDRESS, ADDRESS, ADDRESS); - - private static final MethodHandle CreateWindowExW$MH = LINKER.downcallHandle(LOOKUP.find("CreateWindowExW").get() - , CreateWindowExW$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment CreateWindowExW(int dwExStyle, MemorySegment lpClassName, MemorySegment lpWindowName, - int dwStyle, int X, int Y, int nWidth, int nHeight, - MemorySegment hWndParent, MemorySegment hMenu, - MemorySegment hInstance, MemorySegment lpParam, - MemorySegment lastErrorState) { - try { - return (MemorySegment) CreateWindowExW$MH.invokeExact(lastErrorState, dwExStyle, lpClassName, - lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor RegisterDeviceNotificationW$FUNC = FunctionDescriptor.of(ADDRESS, ADDRESS - , ADDRESS, JAVA_INT); - - private static final MethodHandle RegisterDeviceNotificationW$MH = LINKER.downcallHandle(LOOKUP.find( - "RegisterDeviceNotificationW").get(), RegisterDeviceNotificationW$FUNC, Win.LAST_ERROR_STATE); - - public static MemorySegment RegisterDeviceNotificationW(MemorySegment hRecipient, - MemorySegment NotificationFilter, int Flags, - MemorySegment lastErrorState) { - try { - return (MemorySegment) RegisterDeviceNotificationW$MH.invokeExact(lastErrorState, hRecipient, - NotificationFilter, Flags); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor GetMessageW$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS, - JAVA_INT, JAVA_INT); - - private static final MethodHandle GetMessageW$MH = LINKER.downcallHandle(LOOKUP.find("GetMessageW").get(), - GetMessageW$FUNC, Win.LAST_ERROR_STATE); - - public static int GetMessageW(MemorySegment lpMsg, MemorySegment hWnd, int wMsgFilterMin, int wMsgFilterMax, - MemorySegment lastErrorState) { - try { - return (int) GetMessageW$MH.invokeExact(lastErrorState, lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } -} diff --git a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/WinUSB2.java b/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/WinUSB2.java deleted file mode 100644 index 57aab265..00000000 --- a/java-does-usb/src/main/java/net/codecrete/usb/windows/winsdk/WinUSB2.java +++ /dev/null @@ -1,162 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -package net.codecrete.usb.windows.winsdk; - -import net.codecrete.usb.usbstandard.SetupPacket; -import net.codecrete.usb.windows.Win; - -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.invoke.MethodHandle; - -import static java.lang.foreign.ValueLayout.*; - -/** - * Native function calls for WinUSB. - *

- * This code is manually created to include the additional parameters for capturing - * {@code GetLastError()} until jextract catches up and can generate the corresponding code. - *

- */ -@SuppressWarnings({"OptionalGetWithoutIsPresent", "java:S100", "java:S107", "java:S117"}) -public class WinUSB2 { - private WinUSB2() { - } - - static { - System.loadLibrary("Winusb"); - } - - private static final Linker LINKER = Linker.nativeLinker(); - private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); - - - private static final FunctionDescriptor WinUsb_Initialize$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle WinUsb_Initialize$MH = - LINKER.downcallHandle(LOOKUP.find("WinUsb_Initialize").get(), WinUsb_Initialize$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_Initialize(MemorySegment DeviceHandle, MemorySegment InterfaceHandle, - MemorySegment lastErrorState) { - try { - return (int) WinUsb_Initialize$MH.invokeExact(lastErrorState, DeviceHandle, InterfaceHandle); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_SetCurrentAlternateSetting$FUNC = FunctionDescriptor.of(JAVA_INT, - ADDRESS, JAVA_BYTE); - - private static final MethodHandle WinUsb_SetCurrentAlternateSetting$MH = LINKER.downcallHandle(LOOKUP.find( - "WinUsb_SetCurrentAlternateSetting").get(), WinUsb_SetCurrentAlternateSetting$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_SetCurrentAlternateSetting(MemorySegment InterfaceHandle, byte SettingNumber, - MemorySegment lastErrorState) { - try { - return (int) WinUsb_SetCurrentAlternateSetting$MH.invokeExact(lastErrorState, InterfaceHandle, - SettingNumber); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_ControlTransfer$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - SetupPacket.LAYOUT, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle WinUsb_ControlTransfer$MH = LINKER.downcallHandle(LOOKUP.find( - "WinUsb_ControlTransfer").get(), WinUsb_ControlTransfer$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_ControlTransfer(MemorySegment InterfaceHandle, MemorySegment SetupPacket, - MemorySegment Buffer, int BufferLength, MemorySegment LengthTransferred, - MemorySegment Overlapped, MemorySegment lastErrorState) { - try { - return (int) WinUsb_ControlTransfer$MH.invokeExact(lastErrorState, InterfaceHandle, SetupPacket, Buffer, - BufferLength, LengthTransferred, Overlapped); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_SetPipePolicy$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - JAVA_BYTE, JAVA_INT, JAVA_INT, ADDRESS); - - private static final MethodHandle WinUsb_SetPipePolicy$MH = LINKER.downcallHandle(LOOKUP.find( - "WinUsb_SetPipePolicy").get(), WinUsb_SetPipePolicy$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_SetPipePolicy(MemorySegment InterfaceHandle, byte PipeID, int PolicyType, - int ValueLength, MemorySegment Value, MemorySegment lastErrorState) { - try { - return (int) WinUsb_SetPipePolicy$MH.invokeExact(lastErrorState, InterfaceHandle, PipeID, PolicyType, - ValueLength, Value); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_WritePipe$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, - JAVA_BYTE, ADDRESS, JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle WinUsb_WritePipe$MH = - LINKER.downcallHandle(LOOKUP.find("WinUsb_WritePipe").get(), WinUsb_WritePipe$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_WritePipe(MemorySegment InterfaceHandle, byte PipeID, MemorySegment Buffer, - int BufferLength, MemorySegment LengthTransferred, MemorySegment Overlapped, - MemorySegment lastErrorState) { - try { - return (int) WinUsb_WritePipe$MH.invokeExact(lastErrorState, InterfaceHandle, PipeID, Buffer, - BufferLength, LengthTransferred, Overlapped); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_ReadPipe$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_BYTE - , ADDRESS, JAVA_INT, ADDRESS, ADDRESS); - - private static final MethodHandle WinUsb_ReadPipe$MH = LINKER.downcallHandle(LOOKUP.find("WinUsb_ReadPipe").get() - , WinUsb_ReadPipe$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_ReadPipe(MemorySegment InterfaceHandle, byte PipeID, MemorySegment Buffer, - int BufferLength, MemorySegment LengthTransferred, MemorySegment Overlapped, - MemorySegment lastErrorState) { - try { - return (int) WinUsb_ReadPipe$MH.invokeExact(lastErrorState, InterfaceHandle, PipeID, Buffer, BufferLength - , LengthTransferred, Overlapped); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_ResetPipe$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_BYTE); - - private static final MethodHandle WinUsb_ResetPipe$MH = - LINKER.downcallHandle(LOOKUP.find("WinUsb_ResetPipe").get(), WinUsb_ResetPipe$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_ResetPipe(MemorySegment InterfaceHandle, byte PipeID, MemorySegment lastErrorState) { - try { - return (int) WinUsb_ResetPipe$MH.invokeExact(lastErrorState, InterfaceHandle, PipeID); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } - - private static final FunctionDescriptor WinUsb_AbortPipe$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_BYTE); - - private static final MethodHandle WinUsb_AbortPipe$MH = - LINKER.downcallHandle(LOOKUP.find("WinUsb_AbortPipe").get(), WinUsb_AbortPipe$FUNC, Win.LAST_ERROR_STATE); - - public static int WinUsb_AbortPipe(MemorySegment InterfaceHandle, byte PipeID, MemorySegment lastErrorState) { - try { - return (int) WinUsb_AbortPipe$MH.invokeExact(lastErrorState, InterfaceHandle, PipeID); - } catch (Throwable ex) { - throw new AssertionError(ex); - } - } -} diff --git a/java-does-usb/src/test/java/net/codecrete/usb/AlternateInterfaceTest.java b/java-does-usb/src/test/java/net/codecrete/usb/AlternateInterfaceTest.java index 857b9b61..11f53b2a 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/AlternateInterfaceTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/AlternateInterfaceTest.java @@ -13,7 +13,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; class AlternateInterfaceTest extends TestDeviceBase { @@ -26,39 +29,42 @@ static void precondition() { @Test void selectAlternateIntf_succeeds() { - testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 1); + testDevice.selectAlternateSetting(config.interfaceNumber(), 1); - var altIntf = testDevice.getInterface(LOOPBACK_INTF_LOOPBACK).alternate(); + var altIntf = testDevice.getInterface(config.interfaceNumber()).getCurrentAlternate(); assertNotNull(altIntf); - assertEquals(2, altIntf.endpoints().size()); - assertEquals(0xff, altIntf.classCode()); + assertEquals(2, altIntf.getEndpoints().size()); + assertEquals(0xff, altIntf.getClassCode()); - testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 0); + testDevice.selectAlternateSetting(config.interfaceNumber(), 0); } @Test void selectInvalidAlternateIntf_fails() { - assertThrows(USBException.class, () -> testDevice.selectAlternateSetting(1, 0)); + assertThrows(UsbException.class, () -> testDevice.selectAlternateSetting(1, 0)); - assertThrows(USBException.class, () -> testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 2)); + var interfaceNumber = config.interfaceNumber(); + assertThrows(UsbException.class, () -> testDevice.selectAlternateSetting(interfaceNumber, 2)); } @Test void transferOnValidEndpoint_succeeds() { - testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 1); + testDevice.selectAlternateSetting(config.interfaceNumber(), 1); var sampleData = generateRandomBytes(12, 293872394); - testDevice.transferOut(LOOPBACK_EP_OUT, sampleData); - var received = testDevice.transferIn(LOOPBACK_EP_IN); + testDevice.transferOut(config.endpointLoopbackOut(), sampleData); + var received = testDevice.transferIn(config.endpointLoopbackIn()); assertArrayEquals(sampleData, received); } @Test void transferOnInvalidEndpoint_fails() { - testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 1); + testDevice.selectAlternateSetting(config.interfaceNumber(), 1); - assertThrows(USBException.class, () -> testDevice.transferOut(ECHO_EP_OUT, new byte[] { 1, 2, 3 })); + var endpointOut = config.endpointEchoOut(); + assertThrows(UsbException.class, () -> testDevice.transferOut(endpointOut, new byte[]{1, 2, 3})); - assertThrows(USBException.class, () -> testDevice.transferIn(ECHO_EP_IN)); + var endpointIn = config.endpointEchoIn(); + assertThrows(UsbException.class, () -> testDevice.transferIn(endpointIn)); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/BulkTransferTest.java b/java-does-usb/src/test/java/net/codecrete/usb/BulkTransferTest.java index 2418fd93..1323b380 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/BulkTransferTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/BulkTransferTest.java @@ -15,7 +15,9 @@ import java.util.Arrays; import java.util.concurrent.CompletableFuture; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; class BulkTransferTest extends TestDeviceBase { @@ -39,13 +41,13 @@ void mediumTransfer_succeeds() { @Test void transferWithZLP_succeeds() { - var inEndpoint = testDevice.getEndpoint(USBDirection.IN, LOOPBACK_EP_IN); - var sampleData = generateRandomBytes(inEndpoint.packetSize(), 97333894); - testDevice.transferOut(LOOPBACK_EP_OUT, sampleData); - testDevice.transferOut(LOOPBACK_EP_OUT, new byte[0]); - var data = testDevice.transferIn(LOOPBACK_EP_IN); + var inEndpoint = testDevice.getEndpoint(UsbDirection.IN, config.endpointLoopbackIn()); + var sampleData = generateRandomBytes(inEndpoint.getPacketSize(), 97333894); + testDevice.transferOut(config.endpointLoopbackOut(), sampleData); + testDevice.transferOut(config.endpointLoopbackOut(), new byte[0]); + var data = testDevice.transferIn(config.endpointLoopbackIn()); assertArrayEquals(sampleData, data); - data = testDevice.transferIn(LOOPBACK_EP_IN); + data = testDevice.transferIn(config.endpointLoopbackIn()); assertNotNull(data); assertEquals(0, data.length); } @@ -67,15 +69,16 @@ static void writeBytes(byte[] data) { var numBytes = 0; while (numBytes < data.length) { var size = Math.min(chunkSize, data.length - numBytes); - testDevice.transferOut(LOOPBACK_EP_OUT, Arrays.copyOfRange(data, numBytes, numBytes + size)); + testDevice.transferOut(config.endpointLoopbackOut(), Arrays.copyOfRange(data, numBytes, numBytes + size)); numBytes += size; } } + static byte[] readBytes(int numBytes) { var buffer = new ByteArrayOutputStream(); var bytesRead = 0; while (bytesRead < numBytes) { - var data = testDevice.transferIn(LOOPBACK_EP_IN); + var data = testDevice.transferIn(config.endpointLoopbackIn()); buffer.writeBytes(data); bytesRead += data.length; } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/ControlTransferTest.java b/java-does-usb/src/test/java/net/codecrete/usb/ControlTransferTest.java index f355a044..8a653679 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/ControlTransferTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/ControlTransferTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; /** * Tests control transfers @@ -20,13 +22,14 @@ class ControlTransferTest extends TestDeviceBase { @Test void storeValue_succeeds() { - testDevice.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x01, (short) 10730, (short) interfaceNumber), null); + var setup = new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x01, (short) 10730, (short) config.interfaceNumber()); + assertDoesNotThrow(() -> testDevice.controlTransferOut(setup, null)); } @Test void retrieveValue_isSameAsStored() { - testDevice.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x01, (short) 0x9a41, (short) interfaceNumber), null); - var valueBytes = testDevice.controlTransferIn(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x03, (short) 0, (short) interfaceNumber), 4); + testDevice.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x01, (short) 0x9a41, (short) config.interfaceNumber()), null); + var valueBytes = testDevice.controlTransferIn(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x03, (short) 0, (short) config.interfaceNumber()), 4); var expectedBytes = new byte[]{(byte) 0x41, (byte) 0x9a, (byte) 0x00, (byte) 0x00}; assertArrayEquals(expectedBytes, valueBytes); } @@ -34,8 +37,21 @@ void retrieveValue_isSameAsStored() { @Test void storeValueInDataStage_canBeRetrieved() { var sentValue = new byte[]{(byte) 0x83, (byte) 0x03, (byte) 0xda, (byte) 0x3e}; - testDevice.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x02, (short) 0, (short) interfaceNumber), sentValue); - var retrievedValue = testDevice.controlTransferIn(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x03, (short) 0, (short) interfaceNumber), 4); + testDevice.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x02, (short) 0, (short) config.interfaceNumber()), sentValue); + var retrievedValue = testDevice.controlTransferIn(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x03, (short) 0, (short) config.interfaceNumber()), 4); assertArrayEquals(sentValue, retrievedValue); } + + @Test + void interfaceNumber_canBeRetrieved() { + var response = testDevice.controlTransferIn(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x05, (short) 0, (short) config.interfaceNumber()), 1); + assertEquals(config.interfaceNumber(), response[0] & 0xff); + + if (isCompositeDevce()) { + testDevice.claimInterface(2); + response = testDevice.controlTransferIn(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x05, (short) 0, (short) 2), 1); + assertEquals(2, response[0] & 0xff); + testDevice.releaseInterface(2); + } + } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/DescriptionTest.java b/java-does-usb/src/test/java/net/codecrete/usb/DescriptionTest.java index 122d9832..42097c2f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/DescriptionTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/DescriptionTest.java @@ -11,7 +11,11 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Tests the interface, alternate settings and endpoint descriptions. @@ -20,121 +24,136 @@ class DescriptionTest extends TestDeviceBase { @Test void deviceInfo_isCorrect() { - assertEquals("JavaDoesUSB", testDevice.manufacturer()); - assertEquals(isLoopbackDevice() ? "Loopback" : "Composite", testDevice.product()); - assertEquals(12, testDevice.serialNumber().length()); + assertEquals("JavaDoesUSB", testDevice.getManufacturer()); + assertEquals(isLoopbackDevice() ? "Loopback" : "Composite", testDevice.getProduct()); + assertEquals(12, testDevice.getSerialNumber().length()); - if (interfaceNumber == 2) { - // composite device - assertEquals(0xef, testDevice.classCode()); - assertEquals(0x02, testDevice.subclassCode()); - assertEquals(0x01, testDevice.protocolCode()); - } else { + if (isLoopbackDevice()) { // simple device - assertEquals(0xff, testDevice.classCode()); - assertEquals(0x00, testDevice.subclassCode()); - assertEquals(0x00, testDevice.protocolCode()); + assertEquals(0xff, testDevice.getClassCode()); + assertEquals(0x00, testDevice.getSubclassCode()); + assertEquals(0x00, testDevice.getProtocolCode()); + } else { + // composite device + assertEquals(0xef, testDevice.getClassCode()); + assertEquals(0x02, testDevice.getSubclassCode()); + assertEquals(0x01, testDevice.getProtocolCode()); } var isComposite = isCompositeDevce(); - assertEquals(2, testDevice.usbVersion().major()); - assertEquals(isComposite ? 1 : 0, testDevice.usbVersion().minor()); - assertEquals(0, testDevice.usbVersion().subminor()); + assertEquals(2, testDevice.getUsbVersion().getMajor()); + assertEquals(isComposite ? 1 : 0, testDevice.getUsbVersion().getMinor()); + assertEquals(0, testDevice.getUsbVersion().getSubminor()); - assertEquals(0, testDevice.deviceVersion().major()); - assertEquals(isComposite ? 3 : 7, testDevice.deviceVersion().minor()); - assertEquals(isComposite ? 6 : 4, testDevice.deviceVersion().subminor()); + assertEquals(0, testDevice.getDeviceVersion().getMajor()); + assertEquals(isComposite ? 3 : 7, testDevice.getDeviceVersion().getMinor()); + assertEquals(isComposite ? 6 : 4, testDevice.getDeviceVersion().getSubminor()); } @Test void interfaceDescriptor_isCorrect() { - assertNotNull(testDevice.interfaces()); - assertEquals(interfaceNumber + 1, testDevice.interfaces().size()); + assertNotNull(testDevice.getInterfaces()); + assertEquals(config.interfaceNumber() + 1, testDevice.getInterfaces().size()); - var intf = testDevice.interfaces().get(interfaceNumber); - assertEquals(interfaceNumber, intf.number()); - assertNotNull(intf.alternate()); + var intf = testDevice.getInterfaces().get(config.interfaceNumber()); + assertEquals(config.interfaceNumber(), intf.getNumber()); + assertNotNull(intf.getCurrentAlternate()); assertTrue(intf.isClaimed()); } + @Test + void invalidInterfaceNumber_shouldThrow() { + assertThrows(UsbException.class, () -> testDevice.getInterface(4)); + } + @Test void alternateInterfaceDescriptor_isCorrect() { - var intf = testDevice.interfaces().get(interfaceNumber); - var altIntf = intf.alternate(); - assertNotNull(intf.alternates()); - assertEquals(isLoopbackDevice() ? 2 : 1, intf.alternates().size()); - assertSame(intf.alternates().get(0), altIntf); - assertEquals(0, altIntf.number()); + var intf = testDevice.getInterfaces().get(config.interfaceNumber()); + var altIntf = intf.getCurrentAlternate(); + assertNotNull(intf.getAlternates()); + assertEquals(isLoopbackDevice() ? 2 : 1, intf.getAlternates().size()); + assertSame(intf.getAlternates().getFirst(), altIntf); + assertEquals(0, altIntf.getNumber()); - assertEquals(0xff, altIntf.classCode()); - assertEquals(0x00, altIntf.subclassCode()); - assertEquals(0x00, altIntf.protocolCode()); + assertEquals(0xff, altIntf.getClassCode()); + assertEquals(0x00, altIntf.getSubclassCode()); + assertEquals(0x00, altIntf.getProtocolCode()); if (isLoopbackDevice()) { - altIntf = intf.alternates().get(1); - assertEquals(1, altIntf.number()); + altIntf = intf.getAlternates().get(1); + assertEquals(1, altIntf.getNumber()); - assertEquals(0xff, altIntf.classCode()); - assertEquals(0x00, altIntf.subclassCode()); - assertEquals(0x00, altIntf.protocolCode()); + assertEquals(0xff, altIntf.getClassCode()); + assertEquals(0x00, altIntf.getSubclassCode()); + assertEquals(0x00, altIntf.getProtocolCode()); } } + @SuppressWarnings("java:S5961") @Test void endpointDescriptors_areCorrect() { - var altIntf = testDevice.interfaces().get(interfaceNumber).alternate(); - assertNotNull(altIntf.endpoints()); - assertEquals(isLoopbackDevice() ? 4 : 2, altIntf.endpoints().size()); - - var endpoint = altIntf.endpoints().get(0); - assertEquals(1, endpoint.number()); - assertEquals(USBDirection.OUT, endpoint.direction()); - assertEquals(USBTransferType.BULK, endpoint.transferType()); - assertTrue(endpoint.packetSize() == 64 || endpoint.packetSize() == 512); - - endpoint = altIntf.endpoints().get(1); - assertEquals(2, endpoint.number()); - assertEquals(USBDirection.IN, endpoint.direction()); - assertEquals(USBTransferType.BULK, endpoint.transferType()); - assertTrue(endpoint.packetSize() == 64 || endpoint.packetSize() == 512); + var altIntf = testDevice.getInterfaces().get(config.interfaceNumber()).getCurrentAlternate(); + assertNotNull(altIntf.getEndpoints()); + assertEquals(isLoopbackDevice() ? 4 : 2, altIntf.getEndpoints().size()); + + var endpoint = altIntf.getEndpoints().getFirst(); + assertEquals(1, endpoint.getNumber()); + assertEquals(UsbDirection.OUT, endpoint.getDirection()); + assertEquals(UsbTransferType.BULK, endpoint.getTransferType()); + assertTrue(endpoint.getPacketSize() == 64 || endpoint.getPacketSize() == 512); + + endpoint = altIntf.getEndpoints().get(1); + assertEquals(2, endpoint.getNumber()); + assertEquals(UsbDirection.IN, endpoint.getDirection()); + assertEquals(UsbTransferType.BULK, endpoint.getTransferType()); + assertTrue(endpoint.getPacketSize() == 64 || endpoint.getPacketSize() == 512); if (isLoopbackDevice()) { - endpoint = altIntf.endpoints().get(2); - assertEquals(3, endpoint.number()); - assertEquals(USBDirection.OUT, endpoint.direction()); - assertEquals(USBTransferType.INTERRUPT, endpoint.transferType()); - assertEquals(16, endpoint.packetSize()); - - endpoint = altIntf.endpoints().get(3); - assertEquals(3, endpoint.number()); - assertEquals(USBDirection.IN, endpoint.direction()); - assertEquals(USBTransferType.INTERRUPT, endpoint.transferType()); - assertEquals(16, endpoint.packetSize()); + endpoint = altIntf.getEndpoints().get(2); + assertEquals(3, endpoint.getNumber()); + assertEquals(UsbDirection.OUT, endpoint.getDirection()); + assertEquals(UsbTransferType.INTERRUPT, endpoint.getTransferType()); + assertEquals(16, endpoint.getPacketSize()); + + endpoint = altIntf.getEndpoints().get(3); + assertEquals(3, endpoint.getNumber()); + assertEquals(UsbDirection.IN, endpoint.getDirection()); + assertEquals(UsbTransferType.INTERRUPT, endpoint.getTransferType()); + assertEquals(16, endpoint.getPacketSize()); // test alternate interface 1 - altIntf = testDevice.interfaces().get(interfaceNumber).alternates().get(1); - assertEquals(2, altIntf.endpoints().size()); - - endpoint = altIntf.endpoints().get(0); - assertEquals(1, endpoint.number()); - assertEquals(USBDirection.OUT, endpoint.direction()); - assertEquals(USBTransferType.BULK, endpoint.transferType()); - assertTrue(endpoint.packetSize() == 64 || endpoint.packetSize() == 512); - - endpoint = altIntf.endpoints().get(1); - assertEquals(2, endpoint.number()); - assertEquals(USBDirection.IN, endpoint.direction()); - assertEquals(USBTransferType.BULK, endpoint.transferType()); - assertTrue(endpoint.packetSize() == 64 || endpoint.packetSize() == 512); + altIntf = testDevice.getInterfaces().get(config.interfaceNumber()).getAlternates().get(1); + assertEquals(2, altIntf.getEndpoints().size()); + + endpoint = altIntf.getEndpoints().getFirst(); + assertEquals(1, endpoint.getNumber()); + assertEquals(UsbDirection.OUT, endpoint.getDirection()); + assertEquals(UsbTransferType.BULK, endpoint.getTransferType()); + assertTrue(endpoint.getPacketSize() == 64 || endpoint.getPacketSize() == 512); + + endpoint = altIntf.getEndpoints().get(1); + assertEquals(2, endpoint.getNumber()); + assertEquals(UsbDirection.IN, endpoint.getDirection()); + assertEquals(UsbTransferType.BULK, endpoint.getTransferType()); + assertTrue(endpoint.getPacketSize() == 64 || endpoint.getPacketSize() == 512); } } + @Test + void invalidEndpoint_shouldThrow() { + int nonExistentInEndpoint = isLoopbackDevice() ? 1 : 4; + assertThrows(UsbException.class, () -> testDevice.getEndpoint(UsbDirection.IN, nonExistentInEndpoint)); + assertThrows(UsbException.class, () -> testDevice.getEndpoint(UsbDirection.OUT, 4)); + assertThrows(UsbException.class, () -> testDevice.getEndpoint(UsbDirection.IN, 0)); + assertThrows(UsbException.class, () -> testDevice.getEndpoint(UsbDirection.OUT, 0)); + } + @Test void configurationDescription_isAvailable() { - var expectedLength = isLoopbackDevice() ? 69 : 98; + var expectedLength = isLoopbackDevice() ? 69 : 115; - var configDesc = testDevice.configurationDescriptor(); + var configDesc = testDevice.getConfigurationDescriptor(); assertNotNull(configDesc); assertEquals(expectedLength, configDesc.length); assertEquals(2, configDesc[1]); diff --git a/java-does-usb/src/test/java/net/codecrete/usb/DescriptorTest.java b/java-does-usb/src/test/java/net/codecrete/usb/DescriptorTest.java index 85dc9057..4ad8b7d7 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/DescriptorTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/DescriptorTest.java @@ -2,22 +2,21 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; class DescriptorTest extends TestDeviceBase { @Test void deviceDescriptor_isAvailable() { - var desc = testDevice.deviceDescriptor(); - assertEquals(18, desc.length); - assertEquals(0x01, desc[1]); + var desc = testDevice.getDeviceDescriptor(); + assertThat(desc).hasSize(18); + assertThat(desc[1]).isEqualTo((byte) 0x01); } @Test void configurationDescriptor_isAvailable() { - var desc = testDevice.configurationDescriptor(); - assertTrue(desc.length > 60); - assertEquals(0x02, desc[1]); + var desc = testDevice.getConfigurationDescriptor(); + assertThat(desc).hasSizeGreaterThan(60); + assertThat(desc[1]).isEqualTo((byte) 0x02); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/DeviceEnumerationTest.java b/java-does-usb/src/test/java/net/codecrete/usb/DeviceEnumerationTest.java index 02a3f84e..7d3c259f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/DeviceEnumerationTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/DeviceEnumerationTest.java @@ -17,33 +17,33 @@ class DeviceEnumerationTest extends TestDeviceBase { @Test void getAllDevices_includesLoopback() { - var deviceList = USB.getAllDevices(); + var deviceList = Usb.getDevices(); assertThat(deviceList) .isNotEmpty() - .anyMatch(device -> device.vendorId() == vid && device.productId() == pid); + .anyMatch(device -> device.getVendorId() == config.vid() && device.getProductId() == config.pid()); } @Test void getDevices_includesLoopback() { - var deviceList = USB.getDevices(device -> device.vendorId() == vid && device.productId() == pid); + var deviceList = Usb.findDevices(device -> device.getVendorId() == config.vid() && device.getProductId() == config.pid()); assertThat(deviceList) .isNotEmpty() - .anyMatch(device -> device.vendorId() == vid && device.productId() == pid); + .anyMatch(device -> device.getVendorId() == config.vid() && device.getProductId() == config.pid()); } @Test void getDevicePredicate_returnsLoopback() { - var device = USB.getDevice(dev -> dev.vendorId() == vid && dev.productId() == pid); + var device = Usb.findDevice(dev -> dev.getVendorId() == config.vid() && dev.getProductId() == config.pid()); assertThat(device).isPresent(); - assertThat(device.get().productId()).isEqualTo(pid); - assertThat(device.get().vendorId()).isEqualTo(vid); + assertThat(device.get().getProductId()).isEqualTo(config.pid()); + assertThat(device.get().getVendorId()).isEqualTo(config.vid()); } @Test void getDeviceVidPid_returnsLoopback() { - var device = USB.getDevice(vid, pid); + var device = Usb.findDevice(config.vid(), config.pid()); assertThat(device).isPresent(); - assertThat(device.get().productId()).isEqualTo(pid); - assertThat(device.get().vendorId()).isEqualTo(vid); + assertThat(device.get().getProductId()).isEqualTo(config.pid()); + assertThat(device.get().getVendorId()).isEqualTo(config.vid()); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/DeviceLifecycleTest.java b/java-does-usb/src/test/java/net/codecrete/usb/DeviceLifecycleTest.java index af45e92c..da9b6ee1 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/DeviceLifecycleTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/DeviceLifecycleTest.java @@ -12,52 +12,55 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class DeviceLifecycleTest { - private USBDevice device; + private UsbDevice device; @Test void lifecycle_showsValidState() { device = TestDeviceBase.getDevice(); - var interfaceNumber = TestDeviceBase.getInterfaceNumber(device); + var interfaceNumber = TestDeviceBase.getDeviceConfig().interfaceNumber(); - var intf = device.interfaces().get(interfaceNumber); - assertEquals(interfaceNumber, intf.number()); + var intf = device.getInterfaces().get(interfaceNumber); + assertEquals(interfaceNumber, intf.getNumber()); - assertFalse(device.isOpen()); + assertFalse(device.isOpened()); assertFalse(intf.isClaimed()); - assertThrows(USBException.class, () -> device.claimInterface(interfaceNumber)); - assertThrows(USBException.class, () -> device.releaseInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.claimInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.releaseInterface(interfaceNumber)); device.open(); - assertTrue(device.isOpen()); + assertTrue(device.isOpened()); assertFalse(intf.isClaimed()); - assertThrows(USBException.class, () -> device.open()); - assertThrows(USBException.class, () -> device.releaseInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.open()); + assertThrows(UsbException.class, () -> device.releaseInterface(interfaceNumber)); device.claimInterface(interfaceNumber); - assertTrue(device.isOpen()); + assertTrue(device.isOpened()); assertTrue(intf.isClaimed()); - assertThrows(USBException.class, () -> device.open()); - assertThrows(USBException.class, () -> device.claimInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.open()); + assertThrows(UsbException.class, () -> device.claimInterface(interfaceNumber)); device.releaseInterface(interfaceNumber); - assertTrue(device.isOpen()); + assertTrue(device.isOpened()); assertFalse(intf.isClaimed()); - assertThrows(USBException.class, () -> device.open()); - assertThrows(USBException.class, () -> device.releaseInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.open()); + assertThrows(UsbException.class, () -> device.releaseInterface(interfaceNumber)); device.close(); - assertFalse(device.isOpen()); + assertFalse(device.isOpened()); assertFalse(intf.isClaimed()); - assertThrows(USBException.class, () -> device.claimInterface(interfaceNumber)); - assertThrows(USBException.class, () -> device.releaseInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.claimInterface(interfaceNumber)); + assertThrows(UsbException.class, () -> device.releaseInterface(interfaceNumber)); } @AfterEach diff --git a/java-does-usb/src/test/java/net/codecrete/usb/InterruptTransferTest.java b/java-does-usb/src/test/java/net/codecrete/usb/InterruptTransferTest.java index 5a2379a8..f59ab124 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/InterruptTransferTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/InterruptTransferTest.java @@ -22,14 +22,14 @@ void smallTransfer_succeeds() { "Interrupt transfer only supported by loopback test device"); var sampleData = generateRandomBytes(12, 293872394); - testDevice.transferOut(ECHO_EP_OUT, sampleData); + testDevice.transferOut(config.endpointEchoOut(), sampleData); // receive first echo - var echo = testDevice.transferIn(ECHO_EP_IN); + var echo = testDevice.transferIn(config.endpointEchoIn()); assertArrayEquals(sampleData, echo); // receive second echo - echo = testDevice.transferIn(ECHO_EP_IN); + echo = testDevice.transferIn(config.endpointEchoIn()); assertArrayEquals(sampleData, echo); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/InvalidOperationTest.java b/java-does-usb/src/test/java/net/codecrete/usb/InvalidOperationTest.java index 4ee735cd..4cc8634f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/InvalidOperationTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/InvalidOperationTest.java @@ -16,34 +16,35 @@ class InvalidOperationTest extends TestDeviceBase { @Test void claimInvalidInterface_throws() { + var interfaceNumber = config.interfaceNumber(); // throws error because it's already claimed - Assertions.assertThrows(USBException.class, () -> testDevice.claimInterface(interfaceNumber)); + Assertions.assertThrows(UsbException.class, () -> testDevice.claimInterface(interfaceNumber)); // throws error because it's an invalid interface number - Assertions.assertThrows(USBException.class, () -> testDevice.claimInterface(3)); + Assertions.assertThrows(UsbException.class, () -> testDevice.claimInterface(3)); // throws error because it's an invalid interface number - Assertions.assertThrows(USBException.class, () -> testDevice.claimInterface(888)); + Assertions.assertThrows(UsbException.class, () -> testDevice.claimInterface(888)); } @Test void releaseInvalidInterface_throws() { - Assertions.assertThrows(USBException.class, () -> testDevice.releaseInterface(1)); + Assertions.assertThrows(UsbException.class, () -> testDevice.releaseInterface(1)); } @Test void invalidEndpoint_throws() { - var data = new byte[] { 34, 23, 99, 0, 17 }; + var data = new byte[]{34, 23, 99, 0, 17}; - Assertions.assertThrows(USBException.class, () -> testDevice.transferOut(2, data)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferOut(2, data)); - Assertions.assertThrows(USBException.class, () -> testDevice.transferOut(0, data)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferOut(0, data)); - Assertions.assertThrows(USBException.class, () -> testDevice.transferOut(4, data)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferOut(4, data)); - Assertions.assertThrows(USBException.class, () -> testDevice.transferIn(1)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferIn(1)); - Assertions.assertThrows(USBException.class, () -> testDevice.transferIn(0)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferIn(0)); - Assertions.assertThrows(USBException.class, () -> testDevice.transferIn(5)); + Assertions.assertThrows(UsbException.class, () -> testDevice.transferIn(5)); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/SpeedTest.java b/java-does-usb/src/test/java/net/codecrete/usb/SpeedTest.java index 732bd3bb..0c3b68c2 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/SpeedTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/SpeedTest.java @@ -14,13 +14,14 @@ import java.io.IOException; import java.util.concurrent.CompletableFuture; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class SpeedTest extends TestDeviceBase { @Test void loopback_isFast() throws Throwable { - final var isHighSpeed = testDevice.getEndpoint(USBDirection.IN, LOOPBACK_EP_IN).packetSize() == 512; + final var isHighSpeed = testDevice.getEndpoint(UsbDirection.IN, config.endpointLoopbackIn()).getPacketSize() == 512; final var numBytes = isHighSpeed ? 5000000 : 500000; var sampleData = generateRandomBytes(numBytes, 7219937602343L); @@ -43,15 +44,16 @@ void loopback_isFast() throws Throwable { } static void writeBytes(byte[] data) { - try (var os = testDevice.openOutputStream(LOOPBACK_EP_OUT)) { + try (var os = testDevice.openOutputStream(config.endpointLoopbackOut())) { os.write(data); } catch (IOException e) { throw new RuntimeException(e); } } + static byte[] readBytes(int numBytes) { - try (var is = testDevice.openInputStream(LOOPBACK_EP_IN)) { - var buffer = new byte[numBytes]; + try (var is = testDevice.openInputStream(config.endpointLoopbackIn())) { + var buffer = new byte[numBytes]; var bytesRead = 0; while (bytesRead < numBytes) { var n = is.read(buffer, bytesRead, numBytes - bytesRead); diff --git a/java-does-usb/src/test/java/net/codecrete/usb/StallTest.java b/java-does-usb/src/test/java/net/codecrete/usb/StallTest.java index 6f97fe72..e79903b8 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/StallTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/StallTest.java @@ -18,43 +18,47 @@ class StallTest extends TestDeviceBase { @Test void stalledBulkTransferOut_recovers() { - haltEndpoint(USBDirection.OUT, LOOPBACK_EP_OUT); + var endpointIn = config.endpointLoopbackIn(); + var endpointOut = config.endpointLoopbackOut(); + haltEndpoint(UsbDirection.OUT, endpointOut); - var data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - assertThrows(USBStallException.class, () -> testDevice.transferOut(LOOPBACK_EP_OUT, data)); + var data = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + assertThrows(UsbStallException.class, () -> testDevice.transferOut(endpointOut, data)); - testDevice.clearHalt(USBDirection.OUT, LOOPBACK_EP_OUT); + testDevice.clearHalt(UsbDirection.OUT, endpointOut); - testDevice.transferOut(LOOPBACK_EP_OUT, data); - var receivedData = testDevice.transferIn(LOOPBACK_EP_IN); + testDevice.transferOut(endpointOut, data); + var receivedData = testDevice.transferIn(endpointIn); assertArrayEquals(data, receivedData); } @Test void stalledBulkTransferIn_recovers() { - haltEndpoint(USBDirection.IN, LOOPBACK_EP_IN); + var endpointIn = config.endpointLoopbackIn(); + var endpointOut = config.endpointLoopbackOut(); + haltEndpoint(UsbDirection.IN, endpointIn); - assertThrows(USBStallException.class, () -> testDevice.transferIn(LOOPBACK_EP_IN)); + assertThrows(UsbStallException.class, () -> testDevice.transferIn(endpointIn)); - testDevice.clearHalt(USBDirection.IN, LOOPBACK_EP_IN); + testDevice.clearHalt(UsbDirection.IN, endpointIn); - var data = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2 }; - testDevice.transferOut(LOOPBACK_EP_OUT, data); - var receivedData = testDevice.transferIn(LOOPBACK_EP_IN); + var data = new byte[]{9, 8, 7, 6, 5, 4, 3, 2}; + testDevice.transferOut(endpointOut, data); + var receivedData = testDevice.transferIn(endpointIn); assertArrayEquals(data, receivedData); } @Test void invalidControlTransfer_throws() { - var request = new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, (byte) 0x08, - (short) 0, (short) interfaceNumber); - assertThrows(USBStallException.class, () -> testDevice.controlTransferIn(request, 2)); + var request = new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, (byte) 0x08, + (short) 0, (short) config.interfaceNumber()); + assertThrows(UsbStallException.class, () -> testDevice.controlTransferIn(request, 2)); } - void haltEndpoint(USBDirection direction, int endpointNumber) { + void haltEndpoint(UsbDirection direction, int endpointNumber) { final var SET_FEATURE = 0x03; final var ENDPOINT_HALT = 0x00; - var endpointAddress = (direction == USBDirection.IN ? 0x80 : 0x00) | endpointNumber; - testDevice.controlTransferOut(new USBControlTransfer(USBRequestType.STANDARD, USBRecipient.ENDPOINT, SET_FEATURE, ENDPOINT_HALT, endpointAddress), null); + var endpointAddress = (direction == UsbDirection.IN ? 0x80 : 0x00) | endpointNumber; + testDevice.controlTransferOut(new UsbControlTransfer(UsbRequestType.STANDARD, UsbRecipient.ENDPOINT, SET_FEATURE, ENDPOINT_HALT, endpointAddress), null); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/StreamTest.java b/java-does-usb/src/test/java/net/codecrete/usb/StreamTest.java index fb090bca..4109f7b6 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/StreamTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/StreamTest.java @@ -12,17 +12,22 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; class StreamTest extends TestDeviceBase { @Test void smallTransfer_succeeds() { - var sampleData = generateRandomBytes(12, 293872394); + var sampleData = generateRandomBytes(12, 293872394); writeBytes(sampleData, 100); var data = readBytes(sampleData.length); assertArrayEquals(sampleData, data); @@ -34,17 +39,18 @@ void mediumTransfer_succeeds() { // has an internal buffer of about 500 bytes. var sampleData = generateRandomBytes(140, 97333894); writeBytes(sampleData, 30); - var data = readBytes(sampleData.length); + var data = readBytes(sampleData.length); assertArrayEquals(sampleData, data); } @Test void transferWithZLP_succeeds() { - final var sampleData = generateRandomBytes(2 * LOOPBACK_MAX_PACKET_SIZE, 197007894); + var maxPacketSize = testDevice.getEndpoint(UsbDirection.OUT, config.endpointLoopbackOut()).getPacketSize(); + final var sampleData = generateRandomBytes(2 * maxPacketSize, 197007894); var writer = CompletableFuture.runAsync(() -> { - testDevice.transferOut(LOOPBACK_EP_OUT, Arrays.copyOfRange(sampleData, 0, LOOPBACK_MAX_PACKET_SIZE)); + testDevice.transferOut(config.endpointLoopbackOut(), Arrays.copyOfRange(sampleData, 0, maxPacketSize)); sleep(200); - testDevice.transferOut(LOOPBACK_EP_OUT, Arrays.copyOfRange(sampleData, LOOPBACK_MAX_PACKET_SIZE, 2 * LOOPBACK_MAX_PACKET_SIZE)); + testDevice.transferOut(config.endpointLoopbackOut(), Arrays.copyOfRange(sampleData, maxPacketSize, 2 * maxPacketSize)); }); var reader = CompletableFuture.supplyAsync(() -> readBytes(sampleData.length)); @@ -75,8 +81,107 @@ void largeTransferBigChunks_succeeds() { assertArrayEquals(sampleData, reader.resultNow()); } + @Test + @SuppressWarnings({"java:S2925", "BusyWait"}) + void blockedWriter_canBeAborted() throws InterruptedException { + // A writer that fills the pipe faster than it is drained eventually blocks in write(). + // Aborting the outstanding transfers from another thread must terminate it promptly and + // safely (with an IOException wrapping the USB error) rather than leave it wedged forever. + + final var data = generateRandomBytes(1_000_000, 0x5c7f10ebL); + + final var bytesWritten = new AtomicLong(0); + final var writerError = new AtomicReference(); + final var readerStream = new AtomicReference(); + + // Thread 1: write to the loopback OUT endpoint until it blocks (nothing keeps draining it). + var writer = new Thread(() -> { + try (var os = testDevice.openOutputStream(config.endpointLoopbackOut())) { + var offset = 0; + while (offset < data.length) { + var size = Math.min(100, data.length - offset); + os.write(data, offset, size); + offset += size; + bytesWritten.set(offset); + } + } catch (Throwable t) { + writerError.set(t); + } + }, "loopback-writer"); + + // Thread 2: read a limited amount from the loopback IN endpoint, then stop draining + // (the stream stays open, modelling a stalled consumer that applies back pressure). + var reader = new Thread(() -> { + try { + var is = testDevice.openInputStream(config.endpointLoopbackIn()); + readerStream.set(is); + var buffer = new byte[64]; + var n = is.read(buffer); + assertTrue(n > 0); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, "loopback-reader"); + + try { + writer.start(); + reader.start(); + reader.join(); + + // Wait until the writer is actually blocked: its progress must stall for 300 ms. + var giveUp = System.currentTimeMillis() + 5000; + var lastCount = -1L; + var stableSince = System.currentTimeMillis(); + while (writer.isAlive() && System.currentTimeMillis() < giveUp) { + var count = bytesWritten.get(); + var now = System.currentTimeMillis(); + if (count != lastCount) { + lastCount = count; + stableSince = now; + } else if (now - stableSince >= 300) { + break; + } + Thread.sleep(20); + } + assertTrue(writer.isAlive(), "writer terminated before it could block"); + + // Abort the outstanding OUT transfers from this thread; the blocked writer must unwind. + testDevice.abortTransfers(UsbDirection.OUT, config.endpointLoopbackOut()); + + writer.join(1500); + assertFalse(writer.isAlive(), "writer thread did not terminate within 1.5 s after abort"); + + // It must have unwound because of the abort, not by finishing or dying some other way. + // The stream surfaces the USB error as an IOException (with the UsbException as cause). + var err = writerError.get(); + assertInstanceOf(IOException.class, err); + assertInstanceOf(UsbException.class, err.getCause()); + + } finally { + // Restore a clean device state so subsequent tests are not affected. + var is = readerStream.get(); + if (is != null) { + try { + is.close(); + } catch (IOException _) { + // ignore + } + } + if (writer.isAlive()) { + try { + testDevice.abortTransfers(UsbDirection.OUT, config.endpointLoopbackOut()); + } catch (Exception _) { + // ignore + } + writer.join(1500); + } + resetBuffers(); + drainData(config.endpointLoopbackIn()); + } + } + static void writeBytes(byte[] data, int chunkSize) { - try (var os = testDevice.openOutputStream(LOOPBACK_EP_OUT)) { + try (var os = testDevice.openOutputStream(config.endpointLoopbackOut())) { var numBytes = 0; while (numBytes < data.length) { var size = Math.min(chunkSize, data.length - numBytes); @@ -88,9 +193,10 @@ static void writeBytes(byte[] data, int chunkSize) { throw new RuntimeException(e); } } + static byte[] readBytes(int numBytes) { var buffer = new byte[numBytes]; - try (var is = testDevice.openInputStream(LOOPBACK_EP_IN)) { + try (var is = testDevice.openInputStream(config.endpointLoopbackIn())) { var bytesRead = 0; while (bytesRead < numBytes) { var n = is.read(buffer, bytesRead, numBytes - bytesRead); @@ -108,7 +214,7 @@ static byte[] readBytes(int numBytes) { private static void sleep(int millis) { try { Thread.sleep(millis); - } catch (InterruptedException e) { + } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceBase.java b/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceBase.java index e13a4e40..c0a35a0f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceBase.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceBase.java @@ -18,66 +18,28 @@ * Base class for tests using the test device. */ public class TestDeviceBase { - /** - * Loopback test device vendor ID - */ - static final int VID_LOOPBACK = 0xcafe; - /** - * Loopback test device product ID - */ - static final int PID_LOOPBACK = 0xceaf; - /** - * Loopback test device loopback interface number - */ - static final int LOOPBACK_INTF_LOOPBACK = 0; - /** - * Composite test device vendor ID - */ - static final int VID_COMPOSITE = 0xcafe; - /** - * Composite test device product ID - */ - static final int PID_COMPOSITE = 0xcea0; - /** - * Composite test device loopback interface number - */ - static final int LOOPBACK_INTF_COMPOSITE = 2; - /** - * Interface number of connected test device - */ - protected static int vid = -1; - protected static int pid = -1; - protected static int interfaceNumber = -1; - protected static final int LOOPBACK_EP_OUT = 1; - protected static final int LOOPBACK_EP_IN = 2; - protected static final int LOOPBACK_MAX_PACKET_SIZE = 64; - protected static final int ECHO_EP_OUT = 3; - protected static final int ECHO_EP_IN = 3; - protected static final int ECHO_MAX_PACKET_SIZE = 16; - protected static USBDevice testDevice; - - static USBDevice getDevice() { - var optionalDevice = USB.getDevice(VID_COMPOSITE, PID_COMPOSITE); - if (optionalDevice.isEmpty()) - optionalDevice = USB.getDevice(VID_LOOPBACK, PID_LOOPBACK); - if (optionalDevice.isEmpty()) + + protected static UsbDevice testDevice; + protected static TestDeviceConfig config; + + static UsbDevice getDevice() { + var device = Usb.findDevice(dev -> TestDeviceConfig.getConfig(dev).isPresent()); + if (device.isEmpty()) throw new IllegalStateException("No test device connected"); - return optionalDevice.get(); + return device.get(); } - static int getInterfaceNumber(USBDevice device) { - return device.productId() == PID_COMPOSITE ? LOOPBACK_INTF_COMPOSITE : LOOPBACK_INTF_LOOPBACK; + static TestDeviceConfig getDeviceConfig() { + return TestDeviceConfig.getConfig(getDevice()).orElse(null); } @BeforeAll static void openDevice() { testDevice = getDevice(); - vid = testDevice.vendorId(); - pid = testDevice.productId(); - interfaceNumber = getInterfaceNumber(testDevice); + config = getDeviceConfig(); testDevice.open(); - testDevice.claimInterface(interfaceNumber); + testDevice.claimInterface(config.interfaceNumber()); resetDevice(); } @@ -91,47 +53,44 @@ static void closeDevice() { } static boolean isLoopbackDevice() { - return pid == PID_LOOPBACK; + return !config.isComposite(); } static boolean isCompositeDevce() { - return pid == PID_COMPOSITE; + return config.isComposite(); } private static void resetDevice() { if (isLoopbackDevice()) - testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 0); + testDevice.selectAlternateSetting(config.interfaceNumber(), 0); // reset buffers resetBuffers(); // drain loopback data - while (true) { - try { - testDevice.transferIn(LOOPBACK_EP_IN, 1); - } catch (USBTimeoutException e) { - break; - } - } + drainData(config.endpointLoopbackIn()); // drain interrupt data - if (isLoopbackDevice()) { - while (true) { - try { - testDevice.transferIn(ECHO_EP_IN, 1); - } catch (USBTimeoutException e) { - break; - } - } - } + if (isLoopbackDevice()) + drainData(config.endpointEchoIn()); // reset buffers again resetBuffers(); } static void resetBuffers() { - testDevice.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.INTERFACE, - (byte) 0x04, (short) 0, (short) interfaceNumber), null); + testDevice.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, + (byte) 0x04, (short) 0, (short) config.interfaceNumber()), null); + } + + static void drainData(int endpointNumber) { + while (true) { + try { + testDevice.transferIn(endpointNumber, 5); + } catch (UsbTimeoutException _) { + break; + } + } } static byte[] generateRandomBytes(int numBytes, long seed) { diff --git a/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceConfig.java b/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceConfig.java new file mode 100644 index 00000000..9e386734 --- /dev/null +++ b/java-does-usb/src/test/java/net/codecrete/usb/TestDeviceConfig.java @@ -0,0 +1,66 @@ +// +// Java Does USB +// Copyright (c) 2024 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// +// Configuration information about test device +// + +package net.codecrete.usb; + +import java.util.Optional; +import java.util.stream.Stream; + +/** + * Test device configuration + * @param vid vendor ID + * @param pid product ID + * @param isComposite indicates if this is the composite test device + * @param interfaceNumber interface number for loopback and echo endpoints + * @param endpointLoopbackOut loopback OUT endpoint number + * @param endpointLoopbackIn loopback IN endpoint number + * @param endpointEchoOut echo OUT endpoint number + * @param endpointEchoIn echo IN endpoint number + */ +public record TestDeviceConfig(int vid, int pid, + boolean isComposite, + int interfaceNumber, + int endpointLoopbackOut, int endpointLoopbackIn, + int endpointEchoOut, int endpointEchoIn +) { + + private static final TestDeviceConfig LOOPBACK_DEVICE = new TestDeviceConfig( + 0xcafe, + 0xceaf, + false, + 0, + 1, + 2, + 3, + 3 + ); + + private static final TestDeviceConfig COMPOSITE_DEVICE = new TestDeviceConfig( + 0xcafe, + 0xcea0, + true, + 3, + 1, + 2, + -1, + -1 + ); + + + /** + * Gets the configuration fo the specified USB device. + * @param device USB device + * @return configuration, or empty if the USB device is not a test device + */ + public static Optional getConfig(UsbDevice device) { + return Stream.of(LOOPBACK_DEVICE, COMPOSITE_DEVICE) + .filter(config -> device.getVendorId() == config.vid() && device.getProductId() == config.pid()) + .findFirst(); + } +} diff --git a/java-does-usb/src/test/java/net/codecrete/usb/TimeoutTest.java b/java-does-usb/src/test/java/net/codecrete/usb/TimeoutTest.java index a692aa13..7f5f1cdd 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/TimeoutTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/TimeoutTest.java @@ -21,47 +21,43 @@ class TimeoutTest extends TestDeviceBase { @Test - @Timeout(value = 1, unit = TimeUnit.SECONDS) + @Timeout(value = 2, unit = TimeUnit.SECONDS) void bulkTransferIn_timesOut() { - assertThrows(USBTimeoutException.class, () -> testDevice.transferIn(LOOPBACK_EP_IN, 200)); + var endpointIn = config.endpointLoopbackIn(); + assertThrows(UsbTimeoutException.class, () -> testDevice.transferIn(endpointIn, 200)); } @Test @Timeout(value = 1, unit = TimeUnit.SECONDS) void bulkTransfer_doesNotTimeOut() { var data = generateRandomBytes(20, 7280277392L); - testDevice.transferOut(LOOPBACK_EP_OUT, data); + testDevice.transferOut(config.endpointLoopbackOut(), data); - var received = testDevice.transferIn(LOOPBACK_EP_IN, 200); + var received = testDevice.transferIn(config.endpointLoopbackIn(), 200); assertArrayEquals(data, received); - } @Test @Timeout(value = 1, unit = TimeUnit.SECONDS) void bulkTransferOut_timesOut() { + drainData(config.endpointLoopbackIn()); + var endpointOut = config.endpointLoopbackOut(); + // The test device has an internal buffer of about 2KB for full-speed // and 16KB for high-speed. The first transfer should not time out. final var bufferSize = 32 * testDevice - .getEndpoint(USBDirection.OUT, LOOPBACK_EP_OUT).packetSize(); + .getEndpoint(UsbDirection.OUT, endpointOut).getPacketSize(); var data = generateRandomBytes(100, 9383073929L); - testDevice.transferOut(LOOPBACK_EP_OUT, data, 200); + testDevice.transferOut(endpointOut, data, 200); - assertThrows(USBTimeoutException.class, () -> { + assertThrows(UsbTimeoutException.class, () -> { for (var i = 0; i < bufferSize / data.length; i++) { - testDevice.transferOut(LOOPBACK_EP_OUT, data, 200); + testDevice.transferOut(endpointOut, data, 200); } }); - // drain data in loopback loop - while (true) { - try { - testDevice.transferIn(LOOPBACK_EP_IN, 200); - } catch (USBTimeoutException e) { - break; - } - } + drainData(config.endpointLoopbackIn()); } @Test @@ -70,7 +66,8 @@ void interruptTransferIn_timesOut() { Assumptions.assumeTrue(isLoopbackDevice(), "Interrupt transfer only supported by loopback test device"); - assertThrows(USBTimeoutException.class, () -> testDevice.transferIn(ECHO_EP_IN, 200)); + var endpointIn = config.endpointEchoIn(); + assertThrows(UsbTimeoutException.class, () -> testDevice.transferIn(endpointIn, 200)); } @Test @@ -79,14 +76,14 @@ void interruptTransfer_doesNotTimeOut() { "Interrupt transfer only supported by loopback test device"); var sampleData = generateRandomBytes(12, 293872394); - testDevice.transferOut(ECHO_EP_OUT, sampleData, 200); + testDevice.transferOut(config.endpointEchoOut(), sampleData, 200); // receive first echo - var echo = testDevice.transferIn(ECHO_EP_IN, 200); + var echo = testDevice.transferIn(config.endpointEchoIn(), 200); assertArrayEquals(sampleData, echo); // receive second echo - echo = testDevice.transferIn(ECHO_EP_IN, 200); + echo = testDevice.transferIn(config.endpointEchoIn(), 200); assertArrayEquals(sampleData, echo); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationDescriptors.java b/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationDescriptors.java new file mode 100644 index 00000000..9d98afc9 --- /dev/null +++ b/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationDescriptors.java @@ -0,0 +1,509 @@ +package net.codecrete.usb.common; + +class ConfigurationDescriptors { + + // For convenience, the configuration descriptor are maintained as int arrays. + private static final int[] SIMPLE_INT_ARRAY = new int[] { + // configuration descriptor + 0x09, // bLength + 0x02, // bDescriptorType = configuration + 0x12, 0x00, // wTotalLength + 0x01, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0x34, // bmAttributes + 0x64, // bMaxPower + + // interface descriptor + 0x09, // bLength + 0x04, // bDescriptorType = interface + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x00, // bNumEndpoints + 0xff, // bInterfaceClass + 0xdd, // bInterfaceSubClass + 0xcc, // bInterfaceProtocol + 0x00, // iInterface + }; + + private static final int[] LARGE_COMPOSITE_INT_ARRAY = new int[] { + // configuration descriptor + 0x09, // bLength = 9 + 0x02, // bDescriptorType = configuration + 0x5A, 0x04, // wTotalLength = 1114 + 0x04, // bNumInterfaces = 4 + 0x01, // bConfigurationValue + 0x00, // iConfiguration (string index) + 0xA0, // bmAttributes (remote wakeup) + 0x70, // bMaxPower = 224mA + + // interface association descriptor (IAD) + 0x08, // bLength = 9 + 0x0B, // bDescriptorType = iad + 0x00, // bFirstInterface = 0 + 0x03, // bInterfaceCount = 3 + 0x0E, // bFunctionClass = 0x0E (Video) + 0x03, // bFunctionSubClass = 0x03 (Video Interface Collection) + 0x00, // bFunctionProtocol = 0x00 (Undefined) + 0x00, // iFunction (string index) + + // interface descriptor + 0x09, // bLength + 0x04, // bDescriptorType = interface + 0x00, // bInterfaceNumber = 0 + 0x00, // bAlternateSetting = 0 + 0x01, // bNumEndpoints = 1 + 0x0E, // bInterfaceClass = 0x0E (Video) + 0x01, // bInterfaceSubClass = 0x01 (Video Control) + 0x00, // bInterfaceProtocol = 0x00 (Undefined) + 0x00, // iInterface (string index) + + 0x0E, // bLength = 14 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x01, 0x00, 0x01, 0xA9, 0x00, 0x80, 0xC3, 0xC9, 0x01, 0x02, 0x01, 0x02, + + 0x09, // bLength = 9 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x03, 0x04, 0x01, 0x01, 0x00, 0x02, 0x00, + + 0x09, // bLength = 9 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x03, 0x05, 0x01, 0x01, 0x00, 0x02, 0x00, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, 0x02, 0x6A, 0xD1, 0x49, 0x2C, 0xB8, 0x32, 0x85, 0x44, 0x3E, 0xA8, 0x64, 0x3A, 0x15, 0x23, 0x62, 0xF2, 0x06, 0x01, 0x06, 0x02, 0x3F, 0x00, 0x00, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, 0x06, 0xD0, 0x9E, 0xE4, 0x23, 0x78, 0x11, 0x31, 0x4F, 0xAE, 0x52, 0xD2, 0xFB, 0x8A, 0x8D, 0x3B, 0x48, 0x05, 0x01, 0x03, 0x02, 0xFF, 0x7F, 0x00, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, 0x0F, 0xDC, 0x95, 0x3F, 0x0F, 0x32, 0x26, 0x4E, 0x4C, 0x92, 0xC9, 0xA0, 0x47, 0x82, 0xF4, 0x3B, 0xC8, 0x02, 0x01, 0x03, 0x02, 0x20, 0x01, 0x00, + + 0x1D, // bLength = 29 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, 0x0E, 0xF2, 0x5D, 0xBD, 0xA8, 0x98, 0x1A, 0x4E, 0x47, 0x8D, 0xD0, 0xD9, 0x26, 0x72, 0xD1, 0x94, 0xFA, 0x02, 0x01, 0x03, 0x04, 0xFF, 0xF3, 0xF3, 0xFF, 0x00, + + 0x12, // bLength = 18 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2E, 0x0A, 0x02, + + 0x0B, // bLength = 11 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x03, 0x01, 0x00, 0x00, 0x02, 0x5B, 0x17, 0x00, + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x85, // bEndpointAddress (IN) + 0x03, // bmAttributes (interrupt) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x08, // bInterval = 8 + + 0x06, // bLength = 6 + 0x30, // bDescriptorType = 0x30 (video) + 0x00, 0x00, 0x08, 0x00, + + 0x05, // bLength = 5 + 0x25, // bDescriptorType = 0x25 (CS_ENDPOINT) + 0x03, 0x40, 0x00, + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x01, // bInterfaceNumber = 1 + 0x00, // bAlternateSetting = 0 + 0x00, // bNumEndpoints = 0 + 0x0E, // bInterfaceClass = 0x0E (Video) + 0x02, // bInterfaceSubClass = 0x02 (Video Streaming) + 0x00, // bInterfaceProtocol = 0x00 (Undefined) + 0x00, // iInterface (string index) + + 0x10, // bLength = 16 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x01, 0x03, 0xD9, 0x02, 0x81, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x04, 0x01, 0x06, 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x01, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x60, 0x09, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x02, 0x00, 0x80, 0x02, 0x68, 0x01, 0x00, 0x80, 0x97, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, 0x08, 0x07, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x03, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x00, 0x18, 0x15, 0x00, 0x00, 0x18, 0x15, 0x00, 0x20, 0x1C, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x04, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x00, 0x5E, 0x1A, 0x00, 0x00, 0x5E, 0x1A, 0x00, 0x20, 0x1C, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x05, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0x00, 0x76, 0x2F, 0x00, 0x00, 0x76, 0x2F, 0x00, 0x48, 0x3F, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x06, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0x80, 0x53, 0x3B, 0x00, 0x80, 0x53, 0x3B, 0x00, 0x48, 0x3F, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x06, // bLength = 6 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x0D, 0x01, 0x01, 0x04, + + 0x0B, // bLength = 11 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, 0x02, 0x0B, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x01, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x40, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x10, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x02, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x10, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x03, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x40, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x10, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x04, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x40, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x0A, 0x8B, 0x02, 0x00, 0x01, 0x0A, 0x8B, 0x02, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x05, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x10, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x06, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0x40, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x10, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x07, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x40, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x0A, 0x8B, 0x02, 0x00, 0x01, 0x0A, 0x8B, 0x02, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x08, 0x00, 0x00, 0x0A, 0xA0, 0x05, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x10, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x09, 0x00, 0x00, 0x0A, 0xA0, 0x05, 0x00, 0x40, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x10, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x0A, 0x00, 0x00, 0x0F, 0x70, 0x08, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x10, 0x00, 0x9A, 0x5B, 0x06, 0x00, 0x01, 0x9A, 0x5B, 0x06, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x07, 0x0B, 0x00, 0x00, 0x0F, 0x70, 0x08, 0x00, 0x40, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x10, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x06, // bLength = 6 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x0D, 0x01, 0x01, 0x04, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x04, 0x03, 0x04, 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x01, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x80, 0x97, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, 0x08, 0x07, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x02, 0x00, 0x80, 0x02, 0x68, 0x01, 0x00, 0xA0, 0xF1, 0x04, 0x00, 0xA0, 0xF1, 0x04, 0x00, 0x46, 0x05, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x03, 0x00, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x80, 0xC6, 0x13, 0x00, 0x80, 0xC6, 0x13, 0x00, 0x18, 0x15, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x04, 0x00, 0x80, 0x07, 0x38, 0x04, 0x00, 0xA0, 0x7E, 0x2C, 0x00, 0xA0, 0x7E, 0x2C, 0x00, 0x76, 0x2F, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x06, // bLength = 6 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x0D, 0x01, 0x01, 0x04, + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x01, // bInterfaceNumber = 1 + 0x01, // bAlternateSetting = 1 + 0x01, // bNumEndpoints = 1 + 0x0E, // bInterfaceClass = 0x0E (Video) + 0x02, // bInterfaceSubClass = 0x02 (Video Streaming) + 0x00, // bInterfaceProtocol = 0x00 (Undefined) + 0x00, // iInterface (string index) + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x81, // bEndpointAddress (IN) + 0x05, // bmAttributes (isochronous, async, data) + 0x00, 0x04, // wMaxPacketSize = 1024 + 0x01, // bInterval = 1 + + 0x06, // bLength = 6 + 0x30, // bDescriptorType = superspeed endpoint companion + 0x05, // bMaxBurst = 5 + 0x02, // bmAttributes.isochronous.mult = 2 + 0x00, 0x48, // wBytesPerInterval = 18432 + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x02, // bInterfaceNumber = 2 + 0x00, // bAlternateSetting = 0 + 0x00, // bNumEndpoints = 0 + 0x0E, // bInterfaceClass = 0x0E (Video) + 0x02, // bInterfaceSubClass = 0x02 (Video Streaming) + 0x00, // bInterfaceProtocol = 0x00 (Undefined) + 0x00, // iInterface (string index) + + 0x0E, // bLength = 14 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x01, 0x01, 0x4D, 0x00, 0x82, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, + + 0x1B, // bLength = 27 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x04, 0x03, 0x01, 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x1E, // bLength = 30 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x05, 0x01, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x80, 0x97, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, 0x08, 0x07, 0x00, 0x15, 0x16, 0x05, 0x00, 0x01, 0x15, 0x16, 0x05, 0x00, + + 0x06, // bLength = 6 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x0D, 0x01, 0x01, 0x04, + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x02, // bInterfaceNumber = 2 + 0x01, // bAlternateSetting = 1 + 0x01, // bNumEndpoints = 1 + 0x0E, // bInterfaceClass = 0x0E (Video) + 0x02, // bInterfaceSubClass = 0x02 (Video Streaming) + 0x00, // bInterfaceProtocol = 0x00 (Undefined) + 0x00, // iInterface (string index) + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x82, // bEndpointAddress (IN) + 0x05, // bmAttributes (isochronous, async, data) + 0x00, 0x04, // wMaxPacketSize = 1024 + 0x01, // bInterval = 1 + + 0x06, // bLength = 6 + 0x30, // bDescriptorType = superspeed endpoint companion + 0x00, // bMaxBurst = 0 + 0x02, // bmAttributes.isochronous.mult = 2 + 0x00, 0x0C, // wBytesPerInterval = 3072 + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x03, // bInterfaceNumber = 3 + 0x00, // bAlternateSetting = 0 + 0x01, // bNumEndpoints = 1 + 0x03, // bInterfaceClass = 0x03 (HID) + 0x00, // bInterfaceSubClass = 0x00 (No Subclass) + 0x00, // bInterfaceProtocol = 0x00 (None) + 0x00, // iInterface (string index) + + // HID descriptor + 0x09, // bLength = 9 + 0x21, // bDescriptorType = 0x21 (HID) + 0x10, 0x01, // bcdHID = 1.10 + 0x00, // bCountryCode = 0 (not localized) + 0x01, // bNumDescriptors = 1 + 0x22, // bDescriptorType = 0x22 (report) + 0x46, 0x02, // wDescriptorLength = 582 + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x84, // bEndpointAddress (IN) + 0x03, // bmAttributes (interrupt) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x0A, // bInterval = 10 + + 0x06, // bLength = 6 + 0x30, // bDescriptorType = superspeed endpoint companion + 0x00, // bMaxBurst = 0 + 0x00, // bmAttributes = 0 + 0x40, 0x00 // wBytesPerInterval = 64 + }; + + private static final int[] COMPOSITE_TEST_DEVICE_INT_ARRAY = new int[] { + // configuration descriptor + 0x09, // bLength = 9 + 0x02, // bDescriptorType = configuration + 0x73, 0x00, // wTotalLength = 115 + 0x04, // bNumInterfaces = 4 + 0x01, // bConfigurationValue = 1 + 0x00, // iConfiguration (string index) + 0x80, // bmAttributes = bus powered + 0xFA, // bMaxPower = 500mA + + // interface association descriptor (IAD) + 0x08, // bLength = 8 + 0x0B, // bDescriptorType = iad + 0x00, // bFirstInterface = 0 + 0x02, // bInterfaceCount = 2 + 0x02, // bFunctionClass = 2 (Communications) + 0x02, // bFunctionSubClass = 2 (Abstract) + 0x00, // bFunctionProtocol = 0 (None) + 0x00, // iFunction (string index) + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x00, // bInterfaceNumber = 0 + 0x00, // bAlternateSetting = 0 + 0x01, // bNumEndpoints = 1 + 0x02, // bInterfaceClass = 2 (Communications) + 0x02, // bInterfaceSubClass = 2 (Abstract) + 0x00, // bInterfaceProtocol = 0 (None) + 0x00, // iInterface (string index) + + // CDC header functional descriptor + 0x05, // bLength = 5 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x00, // bDescriptorSubtype = 0 (Header) + 0x20, 0x01, // bcdCDC = 1.20 + + // CDC call management functional descriptor + 0x05, // bLength = 5 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x01, // bDescriptorSubtype = 1 (Call Management) + 0x00, // bmCapabilities = 0 (None) + 0x01, // bDataInterface = 1 (Data Class Interface 1) + + // CDC abstract control management functional descriptor + 0x04, // bLength = 4 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x02, // bDescriptorSubtype = 2 (Abstract Control Management) + 0x02, // bmCapabilities = 2 (Line Coding and Serial State) + + // CDC union functional descriptor + 0x05, // bLength = 5 + 0x24, // bDescriptorType = 0x24 (CS_INTERFACE) + 0x06, // bDescriptorSubtype = 6 (Union) + 0x00, // bMasterInterface = 0 (Communications Class Interface 0) + 0x01, // bSlaveInterface0 = 1 (Data Class Interface 1) + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x83, // bEndpointAddress (IN) + 0x03, // bmAttributes (interrupt) + 0x08, 0x00, // wMaxPacketSize = 8 + 0x10, // bInterval = 16 + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x01, // bInterfaceNumber = 1 + 0x00, // bAlternateSetting = 0 + 0x02, // bNumEndpoints = 2 + 0x0A, // bInterfaceClass = 0x0A (CDC Data) + 0x00, // bInterfaceSubClass = 0 (None) + 0x00, // bInterfaceProtocol = 0 (None) + 0x00, // iInterface (string index) + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x02, // bEndpointAddress (OUT) + 0x02, // bmAttributes (bulk) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x00, // bInterval = 0 + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x81, // bEndpointAddress (IN) + 0x02, // bmAttributes (Bulk) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x00, // bInterval = 0 + + // interface association descriptor (IAD) + 0x08, // bLength = 8 + 0x0B, // bDescriptorType = iad + 0x02, // bFirstInterface = 2 + 0x02, // bInterfaceCount = 2 + 0xFF, // bFunctionClass = 0xFF (Vendor Specific) + 0x00, // bFunctionSubClass = 0 (None) + 0x00, // bFunctionProtocol = 0 (None) + 0x04, // iFunction (string index) + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x02, // bInterfaceNumber = 2 + 0x00, // bAlternateSetting = 0 + 0x00, // bNumEndpoints = 0 + 0xFF, // bInterfaceClass = 0xFF (Vendor Specific) + 0x00, // bInterfaceSubClass = 0 (None) + 0x00, // bInterfaceProtocol = 0 (None) + 0x00, // iInterface (string index) + + // interface descriptor + 0x09, // bLength = 9 + 0x04, // bDescriptorType = interface + 0x03, // bInterfaceNumber = 3 + 0x00, // bAlternateSetting = 0 + 0x02, // bNumEndpoints = 2 + 0xFF, // bInterfaceClass = 0xFF (Vendor Specific) + 0x00, // bInterfaceSubClass = 0 (None) + 0x00, // bInterfaceProtocol = 0 (None) + 0x00, // iInterface (string index) + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x01, // bEndpointAddress (OUT) + 0x02, // bmAttributes (Bulk) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x00, // bInterval = 0 + + // endpoint descriptor + 0x07, // bLength = 7 + 0x05, // bDescriptorType = endpoint + 0x82, // bEndpointAddress (IN) + 0x02, // bmAttributes (Bulk) + 0x40, 0x00, // wMaxPacketSize = 64 + 0x00, // bInterval = 0 + }; + + static final byte[] SIMPLE; + + static final byte[] COMPOSITE_LARGE; + + static final byte[] COMPOSITE_TEST_DEVICE; + + static { + SIMPLE = new byte[SIMPLE_INT_ARRAY.length]; + for (int i = 0; i < SIMPLE_INT_ARRAY.length; i++) + SIMPLE[i] = (byte) SIMPLE_INT_ARRAY[i]; + + COMPOSITE_LARGE = new byte[LARGE_COMPOSITE_INT_ARRAY.length]; + for (int i = 0; i < LARGE_COMPOSITE_INT_ARRAY.length; i++) + COMPOSITE_LARGE[i] = (byte) LARGE_COMPOSITE_INT_ARRAY[i]; + + COMPOSITE_TEST_DEVICE = new byte[COMPOSITE_TEST_DEVICE_INT_ARRAY.length]; + for (int i = 0; i < COMPOSITE_TEST_DEVICE_INT_ARRAY.length; i++) + COMPOSITE_TEST_DEVICE[i] = (byte) COMPOSITE_TEST_DEVICE_INT_ARRAY[i]; + } +} diff --git a/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationParserTest.java b/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationParserTest.java new file mode 100644 index 00000000..f9a65e25 --- /dev/null +++ b/java-does-usb/src/test/java/net/codecrete/usb/common/ConfigurationParserTest.java @@ -0,0 +1,252 @@ +package net.codecrete.usb.common; + +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbTransferType; +import org.junit.jupiter.api.Test; + +import java.lang.foreign.MemorySegment; + +import static net.codecrete.usb.common.ConfigurationDescriptors.COMPOSITE_LARGE; +import static net.codecrete.usb.common.ConfigurationDescriptors.COMPOSITE_TEST_DEVICE; +import static net.codecrete.usb.common.ConfigurationDescriptors.SIMPLE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ConfigurationParserTest { + + @Test + void simpleDescriptor_canBeParsed() { + + var configuration = ConfigurationParser.parseConfigurationDescriptor(MemorySegment.ofArray(SIMPLE)); + + assertThat(configuration.interfaces()) + .hasSize(1) + .singleElement().satisfies(intf -> { + assertThat(intf.getNumber()).isZero(); + assertThat(intf.getAlternates()) + .hasSize(1) + .singleElement().satisfies(altIntf -> { + assertThat(altIntf).isSameAs(intf.getCurrentAlternate()); + assertThat(altIntf.getNumber()).isZero(); + assertThat(altIntf.getEndpoints()).isEmpty(); + assertThat(altIntf.getClassCode()).isEqualTo(0x0ff); + assertThat(altIntf.getSubclassCode()).isEqualTo(0x0dd); + assertThat(altIntf.getProtocolCode()).isEqualTo(0x0cc); + }); + assertThat(intf.isClaimed()).isFalse(); + }); + assertThat(configuration.functions()).hasSize(1); + assertThat(configuration.configValue()).isEqualTo(1); + assertThat(configuration.attributes()).isEqualTo(0x34); + assertThat(configuration.maxPower()).isEqualTo(0x64); + } + + @Test + @SuppressWarnings("java:S5961") + void largeCompositeDescriptor_canBeParsed() { + var configuration = ConfigurationParser.parseConfigurationDescriptor(MemorySegment.ofArray(COMPOSITE_LARGE)); + + // 2 functions + assertThat(configuration.functions()) + .hasSize(2); + + // function 0: 3 interfaces + assertThat(configuration.functions().get(0)).satisfies(function -> { + assertThat(function.firstInterfaceNumber()).isZero(); + assertThat(function.numInterfaces()).isEqualTo(3); + }); + + // function 1: 1 interface + assertThat(configuration.functions().get(1)).satisfies(function -> { + assertThat(function.firstInterfaceNumber()).isEqualTo(3); + assertThat(function.numInterfaces()).isEqualTo(1); + }); + + assertThat(configuration.interfaces()).hasSize(4); + + // interface 0 + assertThat(configuration.interfaces().get(0)).satisfies(intf -> { + assertThat(intf.getNumber()).isZero(); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getCurrentAlternate().getEndpoints()).hasSize(1); + assertThat(intf.getCurrentAlternate().getEndpoints().getFirst()).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(5); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.INTERRUPT); + }); + }); + + // interface 1 + assertThat(configuration.interfaces().get(1)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(1); + assertThat(intf.getAlternates()).hasSize(2); + assertThat(intf.getAlternates().get(0)).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).isEmpty(); + }); + assertThat(intf.getAlternates().get(1)).satisfies(alternate -> { + assertThat(alternate.getNumber()).isEqualTo(1); + assertThat(alternate.getEndpoints()).hasSize(1); + assertThat(alternate.getEndpoints().getFirst()).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(1); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.ISOCHRONOUS); + }); + }); + }); + + // interface 2 + assertThat(configuration.interfaces().get(2)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(2); + assertThat(intf.getAlternates()).hasSize(2); + assertThat(intf.getAlternates().get(0)).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).isEmpty(); + }); + assertThat(intf.getAlternates().get(1)).satisfies(alternate -> { + assertThat(alternate.getNumber()).isEqualTo(1); + assertThat(alternate.getEndpoints()).hasSize(1); + assertThat(alternate.getEndpoints().getFirst()).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(2); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.ISOCHRONOUS); + }); + }); + }); + + // interface 3 + assertThat(configuration.interfaces().get(3)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(3); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getAlternates().getFirst()).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).hasSize(1); + assertThat(alternate.getEndpoints().getFirst()).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(4); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.INTERRUPT); + }); + }); + }); + } + + + @Test + @SuppressWarnings("java:S5961") + void compositeTestDeviceDescriptor_canBeParsed() { + var configuration = ConfigurationParser.parseConfigurationDescriptor(MemorySegment.ofArray(COMPOSITE_TEST_DEVICE)); + + // 2 functions + assertThat(configuration.functions()) + .hasSize(2); + + // function 0: 2 interfaces + assertThat(configuration.functions().get(0)).satisfies(function -> { + assertThat(function.firstInterfaceNumber()).isZero(); + assertThat(function.numInterfaces()).isEqualTo(2); + }); + + // function 1: 2 interfaces + assertThat(configuration.functions().get(1)).satisfies(function -> { + assertThat(function.firstInterfaceNumber()).isEqualTo(2); + assertThat(function.numInterfaces()).isEqualTo(2); + }); + + assertThat(configuration.interfaces()).hasSize(4); + + // interface 0 + assertThat(configuration.interfaces().get(0)).satisfies(intf -> { + assertThat(intf.getNumber()).isZero(); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getCurrentAlternate().getEndpoints()).hasSize(1); + assertThat(intf.getCurrentAlternate().getEndpoints().getFirst()).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(3); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.INTERRUPT); + }); + }); + + // interface 1 + assertThat(configuration.interfaces().get(1)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(1); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getAlternates().getFirst()).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).hasSize(2); + assertThat(alternate.getEndpoints().get(0)).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(2); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.OUT); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.BULK); + }); + assertThat(alternate.getEndpoints().get(1)).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(1); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.BULK); + }); + }); + }); + + // interface 2 + assertThat(configuration.interfaces().get(2)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(2); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getAlternates().getFirst()).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).isEmpty(); + }); + }); + + // interface 3 + assertThat(configuration.interfaces().get(3)).satisfies(intf -> { + assertThat(intf.getNumber()).isEqualTo(3); + assertThat(intf.getAlternates()).hasSize(1); + assertThat(intf.getAlternates().getFirst()).satisfies(alternate -> { + assertThat(alternate.getNumber()).isZero(); + assertThat(alternate.getEndpoints()).hasSize(2); + assertThat(alternate.getEndpoints().get(0)).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(1); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.OUT); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.BULK); + }); + assertThat(alternate.getEndpoints().get(1)).satisfies(endpoint -> { + assertThat(endpoint.getNumber()).isEqualTo(2); + assertThat(endpoint.getDirection()).isEqualTo(UsbDirection.IN); + assertThat(endpoint.getTransferType()).isEqualTo(UsbTransferType.BULK); + }); + }); + }); + } + + @Test + void tooShortDescriptor_throwsException() { + var desc = new byte[COMPOSITE_LARGE.length - 1]; + System.arraycopy(COMPOSITE_LARGE, 0, desc, 0, desc.length); + var segment = MemorySegment.ofArray(desc); + + assertThatThrownBy(() -> ConfigurationParser.parseConfigurationDescriptor(segment)) + .isInstanceOf(UsbException.class) + .hasMessage("invalid USB configuration descriptor (invalid length)"); + } + + @Test + void tooLongDescriptor_throwsException() { + var desc = new byte[COMPOSITE_LARGE.length + 1]; + System.arraycopy(COMPOSITE_LARGE, 0, desc, 0, COMPOSITE_LARGE.length); + var segment = MemorySegment.ofArray(desc); + + assertThatThrownBy(() -> ConfigurationParser.parseConfigurationDescriptor(segment)) + .isInstanceOf(UsbException.class) + .hasMessage("invalid USB configuration descriptor (invalid length)"); + } + + @Test + void invalidDescriptor_throwsException() { + var desc = new byte[]{0x5a, 0x41, 0x03, 0x07}; + var segment = MemorySegment.ofArray(desc); + + assertThatThrownBy(() -> ConfigurationParser.parseConfigurationDescriptor(segment)) + .isInstanceOf(UsbException.class) + .hasMessage("invalid USB configuration descriptor"); + } +} diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/Continuous.java b/java-does-usb/src/test/java/net/codecrete/usb/special/Continuous.java new file mode 100644 index 00000000..c432972b --- /dev/null +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/Continuous.java @@ -0,0 +1,61 @@ +package net.codecrete.usb.special; + +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbException; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Random; + +public class Continuous { + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static void main(String[] args) throws IOException { + var device = Usb.findDevice(0xcafe, 0xceaf) + .or(() -> Usb.findDevice(0xcafe, 0xcea0)) + .orElseThrow(() -> new IllegalStateException("No test device connected")); + var interfaceNumber = device.getProductId() == 0xceaf ? 0 : 3; + + device.open(); + device.claimInterface(interfaceNumber); + + new Thread(() -> readData(device)).start(); + new Thread(() -> sendData(device)).start(); + + System.out.println("Press RETURN to exit"); + System.in.read(); + device.close(); + } + + @SuppressWarnings({"java:S2925", "BusyWait"}) + private static void sendData(UsbDevice device) { + var random = new Random(); + var buffer = new byte[40]; + + while (true) { + random.nextBytes(buffer); + try { + device.transferOut(1, buffer); + Thread.sleep(3000); + } catch (UsbException _) { + return; + } catch (InterruptedException _) { + Thread.currentThread().interrupt(); + } + } + } + + private static void readData(UsbDevice device) { + var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + while (true) { + try { + var packet = device.transferIn(2); + System.out.printf("%s packet of %d bytes received%n", LocalDateTime.now().format(formatter), packet.length); + } catch (UsbException _) { + return; + } + } + } +} diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/EnumerateDevices.java b/java-does-usb/src/test/java/net/codecrete/usb/special/EnumerateDevices.java index 2951df4b..a88ff90f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/special/EnumerateDevices.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/EnumerateDevices.java @@ -7,7 +7,7 @@ package net.codecrete.usb.special; -import net.codecrete.usb.USB; +import net.codecrete.usb.Usb; /** * Sample program displaying the connected USB devices @@ -15,7 +15,7 @@ public class EnumerateDevices { public static void main(String[] args) { - for (var device : USB.getAllDevices()) { + for (var device : Usb.getDevices()) { System.out.println(device); } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/LogicAnalyzer.java b/java-does-usb/src/test/java/net/codecrete/usb/special/LogicAnalyzer.java index e146192a..006f6693 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/special/LogicAnalyzer.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/LogicAnalyzer.java @@ -10,7 +10,13 @@ package net.codecrete.usb.special; -import net.codecrete.usb.*; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbException; +import net.codecrete.usb.UsbRecipient; +import net.codecrete.usb.UsbRequestType; import java.io.Closeable; import java.io.IOException; @@ -46,12 +52,12 @@ public class LogicAnalyzer implements Closeable { /// USB vendor ID - final static int VID = 0x0925; + static final int VID = 0x0925; /// USB product ID - final static int PID = 0x3881; + static final int PID = 0x3881; // bulk endpoint number - final static int EP = 2; + static final int EP = 2; /// Effective sample rate (in Hz) private int effSampleRate; @@ -80,10 +86,10 @@ public static void main(String[] args) { } } - private USBDevice device; + private UsbDevice device; LogicAnalyzer() { - var optionalDevice = USB.getDevice(VID, PID); + var optionalDevice = Usb.findDevice(VID, PID); if (optionalDevice.isEmpty()) throw new IllegalStateException("no logic analyzer connected"); @@ -166,22 +172,22 @@ void startAcquisition() { // Byte 1-2: clock ticks (-1) between two samples (16 bit, big endian) int ticks = period - 1; - byte flags = use48Mhz ? (byte)(1 << 6) : 0; + byte flags = use48Mhz ? (byte) (1 << 6) : 0; var cmd = new byte[3]; cmd[0] = flags; - cmd[1] = (byte)(ticks >> 8); - cmd[2] = (byte)(ticks & 0xff); + cmd[1] = (byte) (ticks >> 8); + cmd[2] = (byte) (ticks & 0xff); // send the start command final int commandCodeStart = 0xb1; - device.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.DEVICE, commandCodeStart, 0, 0), cmd); + device.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.DEVICE, commandCodeStart, 0, 0), cmd); } void saveSamples() { // retrieve the sample data from the bulk endpoint - int expectedSize = (int)(((long)duration * effSampleRate + 500) / 1000); + int expectedSize = (int) (((long) duration * effSampleRate + 500) / 1000); byte[] sampleData = new byte[expectedSize]; @@ -196,7 +202,7 @@ void saveSamples() { activityValue = size; } - } catch (USBException e) { + } catch (UsbException e) { if (!stopped && !bufferOverrunDetected) throw e; @@ -230,7 +236,7 @@ void saveSamples() { void stopAcquisition() { // stop the acquisition by halting the bulk endpoint and clearing the halt stopped = true; - device.abortTransfers(USBDirection.IN, EP); + device.abortTransfers(UsbDirection.IN, EP); } void detectBufferOverrun() { @@ -255,7 +261,7 @@ void detectBufferOverrun() { } void checkFirmware() { - if (device.manufacturer() != null) { + if (device.getManufacturer() != null) { System.out.println("Device ready"); return; } @@ -273,20 +279,20 @@ void checkFirmware() { device.open(); device.claimInterface(0); - byte[] cmd = new byte[] { 1 }; - device.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.DEVICE, 0xa0, 0xe600, 0x0000), cmd); + byte[] cmd = new byte[]{1}; + device.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.DEVICE, 0xa0, 0xe600, 0x0000), cmd); final int len = firmware.length; int offset = 0; while (offset < len) { int n = Math.min(len - offset, 0x1000); byte[] chunk = Arrays.copyOfRange(firmware, offset, offset + n); - device.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.DEVICE, 0xa0, offset, 0x0000), chunk); + device.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.DEVICE, 0xa0, offset, 0x0000), chunk); offset += n; } - cmd = new byte[] { 0 }; - device.controlTransferOut(new USBControlTransfer(USBRequestType.VENDOR, USBRecipient.DEVICE, 0xa0, 0xe600, 0x0000), cmd); + cmd = new byte[]{0}; + device.controlTransferOut(new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.DEVICE, 0xa0, 0xe600, 0x0000), cmd); device.close(); DeviceMonitor.instance().awaitDevice(false); @@ -296,11 +302,11 @@ void checkFirmware() { DeviceMonitor.instance().awaitDevice(true); sleep(200); - var optionalDevice = USB.getDevice(VID, PID); + var optionalDevice = Usb.findDevice(VID, PID); if (optionalDevice.isEmpty()) throw new IllegalStateException("no logic analyzer connected"); device = optionalDevice.get(); - if (device.manufacturer() == null) + if (device.getManufacturer() == null) throw new IllegalStateException("firmware upload failed"); System.out.println("Device is ready"); @@ -309,9 +315,10 @@ void checkFirmware() { void sleep(long milliseconds) { while (true) { try { - Thread.sleep(milliseconds); + //noinspection BusyWait + Thread.sleep(milliseconds); // NOSONAR return; - } catch (InterruptedException e) { + } catch (InterruptedException _) { // ignore and try again } } @@ -334,16 +341,17 @@ static synchronized DeviceMonitor instance() { return singleInstance; } - private DeviceMonitor() { } + private DeviceMonitor() { + } private void start() { - USB.setOnDeviceConnected((device) -> onDeviceConnected(device, true)); - USB.setOnDeviceDisconnected((device) -> onDeviceConnected(device, false)); - isDeviceConnected = USB.getDevice(VID, PID).isPresent(); + Usb.setOnDeviceConnected(dev -> onDeviceConnected(dev, true)); + Usb.setOnDeviceDisconnected(dev -> onDeviceConnected(dev, false)); + isDeviceConnected = Usb.findDevice(VID, PID).isPresent(); } - private void onDeviceConnected(USBDevice device, boolean connected) { - if (device.vendorId() == VID && device.productId() == device.productId()) { + private void onDeviceConnected(UsbDevice device, boolean connected) { + if (device.getVendorId() == VID && device.getProductId() == PID) { try { deviceLock.lock(); isDeviceConnected = connected; diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/MonitorDevices.java b/java-does-usb/src/test/java/net/codecrete/usb/special/MonitorDevices.java index 2aacff50..ebf0df0f 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/special/MonitorDevices.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/MonitorDevices.java @@ -7,12 +7,16 @@ package net.codecrete.usb.special; -import net.codecrete.usb.USB; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbRecipient; +import net.codecrete.usb.UsbRequestType; import java.io.IOException; /** - * Sample program displaying information when USB devices are connected or disconnected. + * Test program that communicates with the device as soon as it has been plugged in. *

* Quit with Ctrl-C or whatever stops a program on your platform. *

@@ -20,14 +24,39 @@ public class MonitorDevices { public static void main(String[] args) throws IOException { - USB.setOnDeviceConnected((device) -> System.out.println("Connected: " + device.toString())); - USB.setOnDeviceDisconnected((device) -> System.out.println("Disconnected: " + device.toString())); + Usb.setOnDeviceConnected(device -> { + System.out.println("Connected: " + device.toString()); + talkToTestDevice(device); + }); + Usb.setOnDeviceDisconnected(device -> System.out.println("Disconnected: " + device.toString())); - for (var device : USB.getAllDevices()) + for (var device : Usb.getDevices()) { System.out.println("Present: " + device.toString()); + talkToTestDevice(device); + } System.out.println("Monitoring..."); //noinspection ResultOfMethodCallIgnored System.in.read(); } + + private static void talkToTestDevice(UsbDevice device) { + if (device.getVendorId() != 0xcafe) + return; // no test device + + int interfaceNumber = device.getProductId() == 0xcea0 ? 2 : 0; + device.open(); + device.claimInterface(interfaceNumber); + var response = device.controlTransferIn( + new UsbControlTransfer(UsbRequestType.VENDOR, UsbRecipient.INTERFACE, + (byte) 0x05, (short) 0, (short) interfaceNumber), + 1 + ); + + if (response.length == 1 || interfaceNumber == response[0]) { + System.out.println("Device responded"); + } else { + System.err.println("Invalid response from device"); + } + } } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/USBSerialTest.java b/java-does-usb/src/test/java/net/codecrete/usb/special/USBSerial.java similarity index 65% rename from java-does-usb/src/test/java/net/codecrete/usb/special/USBSerialTest.java rename to java-does-usb/src/test/java/net/codecrete/usb/special/USBSerial.java index 053aa4f3..ec4e4b67 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/special/USBSerialTest.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/USBSerial.java @@ -7,7 +7,12 @@ package net.codecrete.usb.special; -import net.codecrete.usb.*; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbControlTransfer; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbDirection; +import net.codecrete.usb.UsbRecipient; +import net.codecrete.usb.UsbRequestType; /** * Interacts with a USB CDC device (serial device) directly, without using the @@ -26,10 +31,10 @@ * apply for this test. *

*/ -public class USBSerialTest { +public class USBSerial { public static void main(String[] args) { - for (var device : USB.getAllDevices()) { + for (var device : Usb.getDevices()) { int commInterfaceNum = getCDCCommInterfaceNum(device); if (commInterfaceNum >= 0) { System.out.printf("USB CDC device: %s%n", device); @@ -38,7 +43,7 @@ public static void main(String[] args) { } } - static void interact(USBDevice device, int commInterfaceNum) { + static void interact(UsbDevice device, int commInterfaceNum) { // communication and data interface must have consecutive numbers int dataInterfaceNum = commInterfaceNum + 1; @@ -48,14 +53,14 @@ static void interact(USBDevice device, int commInterfaceNum) { device.claimInterface(dataInterfaceNum); // set line coding (9600bps, 8 bit) - byte[] coding = { (byte)0x80, 0x25, 0, 0, 0, 0, 8 }; + byte[] coding = {(byte) 0x80, 0x25, 0, 0, 0, 0, 8}; device.controlTransferOut( - new USBControlTransfer(USBRequestType.CLASS, USBRecipient.INTERFACE, 0x20, 0, commInterfaceNum), + new UsbControlTransfer(UsbRequestType.CLASS, UsbRecipient.INTERFACE, 0x20, 0, commInterfaceNum), coding); // send some data int dataOutEp = getDataOutEndpointNum(device, dataInterfaceNum); - byte[] data = { 'H', 'e', 'l', 'l', 'o', '\r', '\n' }; + byte[] data = {'H', 'e', 'l', 'l', 'o', '\r', '\n'}; device.transferOut(dataOutEp, data); // close device and interfaces @@ -64,29 +69,29 @@ static void interact(USBDevice device, int commInterfaceNum) { device.close(); } - static int getCDCCommInterfaceNum(USBDevice device) { + static int getCDCCommInterfaceNum(UsbDevice device) { // CDC ACM implementations consist of two consecutive interfaces // with certain class, subclass and protocol codes - int numInterfaces = device.interfaces().size(); + int numInterfaces = device.getInterfaces().size(); if (numInterfaces < 2) return -1; for (int i = 0; i < numInterfaces - 1; i += 1) { - var commIntf = device.getInterface(i).alternate(); - var dataIntf = device.getInterface(i + 1).alternate(); + var commIntf = device.getInterface(i).getCurrentAlternate(); + var dataIntf = device.getInterface(i + 1).getCurrentAlternate(); - if (commIntf.classCode() == 2 && commIntf.subclassCode() == 2 && commIntf.protocolCode() == 1 && dataIntf.classCode() == 10) + if (commIntf.getClassCode() == 2 && commIntf.getSubclassCode() == 2 && commIntf.getProtocolCode() == 1 && dataIntf.getClassCode() == 10) return i; } return -1; } - static int getDataOutEndpointNum(USBDevice device, int dataInterfaceNum) { - var altInterface = device.getInterface(dataInterfaceNum).alternate(); - for (var endpoint : altInterface.endpoints()) { - if (endpoint.direction() == USBDirection.OUT) - return endpoint.number(); + static int getDataOutEndpointNum(UsbDevice device, int dataInterfaceNum) { + var altInterface = device.getInterface(dataInterfaceNum).getCurrentAlternate(); + for (var endpoint : altInterface.getEndpoints()) { + if (endpoint.getDirection() == UsbDirection.OUT) + return endpoint.getNumber(); } return -1; } diff --git a/java-does-usb/src/test/java/net/codecrete/usb/special/Unplug.java b/java-does-usb/src/test/java/net/codecrete/usb/special/Unplug.java index 198ef74a..abba3d4c 100644 --- a/java-does-usb/src/test/java/net/codecrete/usb/special/Unplug.java +++ b/java-does-usb/src/test/java/net/codecrete/usb/special/Unplug.java @@ -7,14 +7,16 @@ package net.codecrete.usb.special; -import net.codecrete.usb.USB; -import net.codecrete.usb.USBDevice; -import net.codecrete.usb.USBException; +import net.codecrete.usb.TestDeviceConfig; +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbException; import java.io.IOException; import java.util.HashMap; +import java.util.Map; -import static java.time.Duration.*; +import static java.time.Duration.ofSeconds; /** * Test for robustness when USB devices is unplugged during operation. @@ -24,73 +26,76 @@ *

*/ public class Unplug { - /** - * Loopback test device vendor ID - */ - static final int VID_LOOPBACK = 0xcafe; - /** - * Loopback test device product ID - */ - static final int PID_LOOPBACK = 0xceaf; - /** - * Loopback test device loopback interface number - */ - static final int LOOPBACK_INTF = 0; - - private static final int LOOPBACK_EP_OUT = 1; - private static final int LOOPBACK_EP_IN = 2; - private static final int ECHO_EP_OUT = 3; - private static final int ECHO_EP_IN = 3; - - private static final HashMap activeDevices = new HashMap<>(); + private static final Map activeDevices = new HashMap<>(); - public static void main(String[] args) throws IOException { + static void main() throws IOException { System.out.println("Plug and unplug test device multiple times."); System.out.println("Hit ENTER to exit."); - USB.setOnDeviceConnected(Unplug::onPluggedDevice); - USB.setOnDeviceDisconnected(Unplug::onUnpluggedDevice); - USB.getAllDevices().forEach(Unplug::onPluggedDevice); + Usb.setOnDeviceConnected(Unplug::onPluggedDevice); + Usb.setOnDeviceDisconnected(Unplug::onUnpluggedDevice); + Usb.getDevices().forEach(Unplug::onPluggedDevice); //noinspection ResultOfMethodCallIgnored System.in.read(); } - private static void onPluggedDevice(USBDevice device) { - if (!isTestDevice(device)) + private static void onPluggedDevice(UsbDevice device) { + var config = TestDeviceConfig.getConfig(device); + if (config.isEmpty()) return; - var worker = new DeviceWorker(device); + var worker = new DeviceWorker(device, config.get()); activeDevices.put(device, worker); worker.start(); } - private static void onUnpluggedDevice(USBDevice device) { - if (!isTestDevice(device)) + private static void onUnpluggedDevice(UsbDevice device) { + var config = TestDeviceConfig.getConfig(device); + if (config.isEmpty()) return; var worker = activeDevices.remove(device); worker.setDisconnectTime(System.currentTimeMillis()); worker.join(); + + // test handling of disconnected devices + new Thread(() -> { + sleep(2000); + try { + device.open(); + System.err.println("Device should not be openable after disconnect"); + } catch (UsbException e) { + if (!e.getMessage().contains("disconnected")) + System.err.println("Unexpected error: " + e.getMessage()); + } + }).start(); } - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - private static boolean isTestDevice(USBDevice device) { - return device.vendorId() == VID_LOOPBACK && device.productId() == PID_LOOPBACK; + @SuppressWarnings({"SameParameterValue", "java:S2925"}) + private static void sleep(long millis) { + try { + Thread.sleep(millis); + + } catch (InterruptedException _) { + Thread.currentThread().interrupt(); + } } static class DeviceWorker { - private final USBDevice device; + private final UsbDevice device; + private final TestDeviceConfig config; private final int seed; private long disconnectTime; - private final HashMap workTracking = new HashMap<>(); + private final Map workTracking = new HashMap<>(); - DeviceWorker(USBDevice device) { + DeviceWorker(UsbDevice device, TestDeviceConfig config) { this.device = device; + this.config = config; this.seed = (int) System.currentTimeMillis(); } @@ -98,15 +103,17 @@ void start() { System.out.println("Device connected"); device.open(); - device.claimInterface(LOOPBACK_INTF); + device.claimInterface(config.interfaceNumber()); // start loopback sender and receiver startThread((seed & 1) != 0 ? this::sendLoopbackDataStream : this::sendLoopbackData); startThread((seed & 2) != 0 ? this::receiveLoopbackDataStream : this::receiveLoopbackData); // start echo sender and receiver - startThread(this::sendEcho); - startThread(this::receiveEcho); + if (config.endpointEchoOut() > 0) { + startThread(this::sendEcho); + startThread(this::receiveEcho); + } } private void startThread(Runnable action) { @@ -174,7 +181,7 @@ private void logWork(long amount) { private void runAction(Runnable action) { try { action.run(); - } catch (USBException e) { + } catch (UsbException _) { logFinish(); } } @@ -186,7 +193,7 @@ private void sendLoopbackData() { //noinspection InfiniteLoopStatement while (true) { prng.fill(data); - device.transferOut(LOOPBACK_EP_OUT, data, 1000); + device.transferOut(config.endpointLoopbackOut(), data, 1000); logWork(data.length); } } @@ -196,7 +203,7 @@ private void receiveLoopbackData() { var prng = new PRNG(); //noinspection InfiniteLoopStatement while (true) { - byte[] data = device.transferIn(LOOPBACK_EP_IN); + byte[] data = device.transferIn(config.endpointLoopbackIn()); int index = prng.verify(data); if (index >= 0) throw new RuntimeException("invalid data received"); @@ -208,7 +215,7 @@ private void sendLoopbackDataStream() { logStart("sending loopback data with output stream", 300_000); var prng = new PRNG(); var data = new byte[5000]; - try (var os = device.openOutputStream(LOOPBACK_EP_OUT)) { + try (var os = device.openOutputStream(config.endpointLoopbackOut())) { //noinspection InfiniteLoopStatement while (true) { prng.fill(data); @@ -216,6 +223,8 @@ private void sendLoopbackDataStream() { logWork(data.length); } } catch (IOException e) { + if (e.getCause() instanceof UsbException usbException) + throw usbException; throw new RuntimeException(e); } } @@ -223,7 +232,7 @@ private void sendLoopbackDataStream() { private void receiveLoopbackDataStream() { logStart("receiving loopback data with input stream", 300_000); var prng = new PRNG(); - try (var is = device.openInputStream(LOOPBACK_EP_IN)) { + try (var is = device.openInputStream(config.endpointLoopbackIn())) { //noinspection InfiniteLoopStatement while (true) { var data = new byte[2000]; @@ -234,16 +243,18 @@ private void receiveLoopbackDataStream() { logWork(n); } } catch (IOException e) { + if (e.getCause() instanceof UsbException usbException) + throw usbException; throw new RuntimeException(e); } } private void sendEcho() { logStart("sending echo", 7); - var data = new byte[] { 0x03, 0x45, 0x73, (byte)0xb3, (byte)0x9f, 0x3f, 0x00, 0x6a }; + var data = new byte[]{0x03, 0x45, 0x73, (byte) 0xb3, (byte) 0x9f, 0x3f, 0x00, 0x6a}; //noinspection InfiniteLoopStatement while (true) { - device.transferOut(ECHO_EP_OUT, data); + device.transferOut(config.endpointEchoOut(), data); logWork(1); sleep(100); } @@ -253,20 +264,10 @@ private void receiveEcho() { logStart("receiving echo", 14); //noinspection InfiniteLoopStatement while (true) { - device.transferIn(ECHO_EP_IN); + device.transferIn(config.endpointEchoIn()); logWork(1); } } - - @SuppressWarnings("SameParameterValue") - private static void sleep(long millis) { - try { - Thread.sleep(millis); - - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } } static class Work { diff --git a/java-does-usb/src/test/java/net/codecrete/usb/usbstandard/StringDescriptorTest.java b/java-does-usb/src/test/java/net/codecrete/usb/usbstandard/StringDescriptorTest.java new file mode 100644 index 00000000..d2b638be --- /dev/null +++ b/java-does-usb/src/test/java/net/codecrete/usb/usbstandard/StringDescriptorTest.java @@ -0,0 +1,107 @@ +package net.codecrete.usb.usbstandard; + +import net.codecrete.usb.UsbException; +import org.junit.jupiter.api.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class StringDescriptorTest { + + @Test + void validStringDescriptor() { + testDescriptor( + new byte[]{0x0c, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0}, + stringDescriptor -> { + assertThat(stringDescriptor.isValid()).isTrue(); + assertThat(stringDescriptor.string()).isEqualTo("Hello"); + } + ); + } + + @Test + void truncateTrailingZeros() { + testDescriptor( + new byte[]{0x0e, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, 0, 0}, + stringDescriptor -> { + assertThat(stringDescriptor.isValid()).isTrue(); + assertThat(stringDescriptor.string()).isEqualTo("Hello"); + } + ); + } + + @Test + void invalidDescriptorType() { + testDescriptor( + new byte[]{0x0c, 0x04, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0}, + stringDescriptor -> assertThat(stringDescriptor.isValid()).isFalse() + ); + } + + @Test + void inconsistentLength() { + testDescriptor( + new byte[]{0x0c, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, 0, 0}, + stringDescriptor -> assertThat(stringDescriptor.isValid()).isFalse() + ); + } + + @Test + void inconsistentLengthThrowsException() { + testDescriptor( + new byte[]{0x0c, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, 0, 0}, + stringDescriptor -> { + assertThat(stringDescriptor.isValid()).isFalse(); + assertThatThrownBy(stringDescriptor::string) + .isInstanceOf(UsbException.class) + .hasMessage("String descriptor is invalid"); + } + ); + } + + @Test + void oddLength() { + testDescriptor( + new byte[]{0x0d, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, 0}, + stringDescriptor -> assertThat(stringDescriptor.isValid()).isFalse() + ); + } + + @Test + void unicodeSurrogates() { + // In theory, USB is stuck with an old Unicode standard and the below is invalid. + // In practice, it will work anyway. + testDescriptor( + new byte[]{0x06, 0x03, 0x3D, (byte) 0xD8, 0x1B, (byte) 0xDE}, + stringDescriptor -> { + assertThat(stringDescriptor.isValid()).isTrue(); + assertThat(stringDescriptor.string()).isEqualTo("\uD83D\uDE1B"); + } + ); + } + + @Test + void invalidUnicodeCharactersAreReplaced() { + testDescriptor( + new byte[]{0x06, 0x03, 'H', 0, 0x1B, (byte) 0xDE}, + stringDescriptor -> { + assertThat(stringDescriptor.isValid()).isTrue(); + assertThat(stringDescriptor.string()).isEqualTo("H�"); + } + ); + } + + private void testDescriptor(byte[] descriptorBytes, Consumer validator) { + try (var arena = Arena.ofConfined()) { + var memorySegment = arena.allocate(descriptorBytes.length); + memorySegment.copyFrom(MemorySegment.ofArray(descriptorBytes)); + + var stringDescriptor = new StringDescriptor(memorySegment); + validator.accept(stringDescriptor); + } + } +} diff --git a/java-does-usb/src/test/resources/tinylog.properties b/java-does-usb/src/test/resources/tinylog.properties new file mode 100644 index 00000000..9cf0c142 --- /dev/null +++ b/java-does-usb/src/test/resources/tinylog.properties @@ -0,0 +1,3 @@ +writer = console +writer.format = {date: HH:mm:ss.SSS} {level|size=5} [{class|size=40}] {message} +writer.level = info diff --git a/reference/README.md b/reference/README.md index 6b5c71d1..a8d4b960 100644 --- a/reference/README.md +++ b/reference/README.md @@ -6,4 +6,4 @@ The C++ code contains less error checking, less test cases and does not cover al - [MacOS](macos) (for use with Xcode) - [Windows](windows) (for use with Visual Studio) -- [LInux](linux) (for use with CMake) +- [Linux](linux) (for use with CMake) diff --git a/reference/linux/usb_device.cpp b/reference/linux/usb_device.cpp index 387d4040..7d70c05d 100644 --- a/reference/linux/usb_device.cpp +++ b/reference/linux/usb_device.cpp @@ -314,6 +314,6 @@ void usb_device::submit_urb(usbdevfs_urb* urb) { void usb_device::cancel_urb(usbdevfs_urb* urb) { int result = ioctl(fd_, USBDEVFS_DISCARDURB, urb); - if (result < 0) - usb_error::throw_error("Failed to submit URB"); + if (result < 0 && errno != EINVAL) + usb_error::throw_error("Failed to cancel URB"); } diff --git a/reference/linux/usb_registry.cpp b/reference/linux/usb_registry.cpp index 865b2632..6ed42b4f 100644 --- a/reference/linux/usb_registry.cpp +++ b/reference/linux/usb_registry.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,7 @@ usb_registry::usb_registry() : monitor_wake_event_fd(-1), on_connected_callback(nullptr), on_disconnected_callback(nullptr), is_device_list_ready(false), - async_io_update_event_fd(-1), async_io_update_request(0), async_io_update_response(0) { + async_io_epoll_fd(-1), async_io_exit_event_fd(-1) { } usb_registry::~usb_registry() { @@ -38,10 +39,10 @@ usb_registry::~usb_registry() { monitor_thread.join(); ::close(monitor_wake_event_fd); - if (async_io_update_event_fd != -1) { - eventfd_write(async_io_update_event_fd, 999999); + if (async_io_exit_event_fd != -1) { + eventfd_write(async_io_exit_event_fd, 999999); async_io_thread.join(); - ::close(async_io_update_event_fd); + ::close(async_io_exit_event_fd); } } @@ -251,66 +252,38 @@ std::shared_ptr usb_registry::get_shared_ptr(usb_device* device) { void usb_registry::async_io_run() { - { - std::lock_guard lock(async_io_mutex); - async_io_update_response = async_io_update_request; - async_io_condition.notify_all(); - } - - std::vector fds; - fds.resize(2); - fds[0].fd = async_io_update_event_fd; - fds[0].events = POLLIN; - while (true) { - - int num_fds = 1; - fds.resize(async_io_fds.size() + 1); - - { - std::lock_guard lock(async_io_mutex); - for (auto fd : async_io_fds) { - fds[num_fds].fd = fd; - fds[num_fds].events = POLLIN | POLLOUT; - num_fds += 1; - } - } - - int ret = poll(fds.data(), num_fds, -1); - if (ret < 0) - usb_error::throw_error("internal error (poll)"); - - for (auto it = fds.begin(); it != fds.end(); ++it) { - if (it->revents == 0) + struct epoll_event events[5]; + int ret = epoll_wait(async_io_epoll_fd, &events[0], 5, -1); + if (ret < 0) { + if (errno == EINTR) continue; + usb_error::throw_error("internal error (epoll)"); + } + + for (int i = 0; i < ret; i++) { + int fd = events[i].data.fd; + if (fd == async_io_exit_event_fd) + return; + reap_urbs(fd); + } + } +} - if (it->fd == async_io_update_event_fd) { - eventfd_t value = 0; - eventfd_read(async_io_update_event_fd, &value); - if (value >= 999999) - return; - - std::lock_guard lock(async_io_mutex); - async_io_update_response = async_io_update_request; - async_io_condition.notify_all(); - continue; - } - - if ((it->revents & POLLERR) != 0) { - // TODO - continue; - } - - if (it->revents != 0) { - usbdevfs_urb* urb = nullptr; - ret = ioctl(it->fd, USBDEVFS_REAPURB, &urb); - if (ret < 0) - usb_error::throw_error("internal error (reap URB)"); - - auto completion = reinterpret_cast(urb->usercontext); - (*completion)(); - } +void usb_registry::reap_urbs(int fd) { + while (true) { + usbdevfs_urb* urb = nullptr; + int ret = ioctl(fd, USBDEVFS_REAPURB, &urb); + if (ret < 0) { + if (errno == EAGAIN) + return; // no more pending URBs + if (errno == ENODEV) + return; // ignore, device might have been closed + usb_error::throw_error("internal error (reap URB)"); } + + auto completion = reinterpret_cast(urb->usercontext); + (*completion)(); } } @@ -321,50 +294,38 @@ void usb_registry::add_async_fd(int fd) { std::lock_guard lock(async_io_mutex); // start background thread if needed - if (async_io_update_event_fd == -1) { - async_io_update_event_fd = eventfd(0, 0); - if (async_io_update_event_fd < 0) + if (async_io_exit_event_fd == -1) { + async_io_exit_event_fd = eventfd(0, 0); + if (async_io_exit_event_fd < 0) usb_error::throw_error("internal error(eventfd)"); - async_io_thread = std::thread(&usb_registry::async_io_run, this); - } - - if (std::find(async_io_fds.begin(), async_io_fds.end(), fd) != async_io_fds.end()) - return; // already registered + async_io_epoll_fd = epoll_create(4); + if (async_io_epoll_fd < 0) + usb_error::throw_error("internal error(epoll_create)"); - async_io_fds.emplace_back(fd); - eventfd_write(async_io_update_event_fd, 1); + epoll_event event = {0}; + event.events = EPOLLIN; + event.data.fd = async_io_exit_event_fd; + int ret = epoll_ctl(async_io_epoll_fd, EPOLL_CTL_ADD, async_io_exit_event_fd, &event); + if (ret < 0) + usb_error::throw_error("internal error(epoll_ctl)"); - async_io_update_request += 1; - expected_request = async_io_update_request; + async_io_thread = std::thread(&usb_registry::async_io_run, this); + } } - // wait for background process to add file descriptor for polling - { - std::unique_lock wait_lock(async_io_mutex); - async_io_condition.wait(wait_lock, [this, expected_request] { return expected_request - async_io_update_response <= 0; }); - } + epoll_event event = {0}; + event.events = EPOLLOUT; + event.data.fd = fd; + int ret = epoll_ctl(async_io_epoll_fd, EPOLL_CTL_ADD, fd, &event); + if (ret < 0) + usb_error::throw_error("internal error(epoll_ctl)"); } void usb_registry::remove_async_fd(int fd) { - int expected_request; - - { - std::lock_guard lock(async_io_mutex); - - async_io_fds.erase( - std::remove(async_io_fds.begin(), async_io_fds.end(), fd), - async_io_fds.end() - ); - async_io_update_request += 1; - expected_request = async_io_update_request; - eventfd_write(async_io_update_event_fd, 1); - } - - // wait for background process to remove file descriptor from polling - { - std::unique_lock wait_lock(async_io_mutex); - async_io_condition.wait(wait_lock, [this, expected_request] { return expected_request - async_io_update_response <= 0; }); - } + epoll_event event = {0}; + int ret = epoll_ctl(async_io_epoll_fd, EPOLL_CTL_DEL, fd, &event); + if (ret < 0) + usb_error::throw_error("internal error(epoll_ctl)"); } diff --git a/reference/linux/usb_registry.hpp b/reference/linux/usb_registry.hpp index 6a95dcb2..ff251eaf 100644 --- a/reference/linux/usb_registry.hpp +++ b/reference/linux/usb_registry.hpp @@ -52,6 +52,7 @@ class usb_registry { void async_io_run(); void add_async_fd(int fd); void remove_async_fd(int fd); + void reap_urbs(int fd); std::shared_ptr create_device(udev_device* udev_dev); std::shared_ptr get_shared_ptr(usb_device* device); @@ -69,11 +70,8 @@ class usb_registry { std::thread async_io_thread; std::mutex async_io_mutex; - std::condition_variable async_io_condition; - std::vector async_io_fds; - int async_io_update_event_fd; - int async_io_update_request; - int async_io_update_response; + int async_io_epoll_fd; + int async_io_exit_event_fd; friend usb_device; }; diff --git a/reference/windows/USB/USB.vcxproj b/reference/windows/USB/USB.vcxproj index 62063b27..46f41a29 100644 --- a/reference/windows/USB/USB.vcxproj +++ b/reference/windows/USB/USB.vcxproj @@ -22,12 +22,12 @@ + - @@ -37,12 +37,12 @@ + - diff --git a/reference/windows/USB/USB.vcxproj.filters b/reference/windows/USB/USB.vcxproj.filters index 7de3d949..473ed8c6 100644 --- a/reference/windows/USB/USB.vcxproj.filters +++ b/reference/windows/USB/USB.vcxproj.filters @@ -33,9 +33,6 @@ Source Files - - Source Files - Source Files @@ -51,6 +48,9 @@ Source Files + + Source Files + @@ -71,9 +71,6 @@ Header Files - - Header Files - Header Files @@ -92,5 +89,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/reference/windows/USB/device_info_set.cpp b/reference/windows/USB/device_info_set.cpp new file mode 100644 index 00000000..6450ec20 --- /dev/null +++ b/reference/windows/USB/device_info_set.cpp @@ -0,0 +1,245 @@ +// +// Java Does USB +// Copyright (c) 2023 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// +// Reference C++ code for Windows +// + +#include "device_info_set.h" +#include "usb_error.hpp" +#include "scope.hpp" +#include + +device_info_set::device_info_set(HDEVINFO dev_info_set) + : dev_info_set_(dev_info_set), dev_info_data_({ sizeof(dev_intf_data_) }), + has_dev_intf_data_(false), dev_intf_data_({ sizeof(dev_intf_data_) }), iteration_index(-1) +{ +} + +device_info_set device_info_set::of_present_devices(const GUID& interface_guid, const std::wstring& instance_id) { + auto dev_info_set = SetupDiGetClassDevsW(&interface_guid, !instance_id.empty() ? instance_id.c_str() : nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info_set == INVALID_HANDLE_VALUE) + usb_error::throw_error("internal error (SetupDiGetClassDevsW)"); + return device_info_set(dev_info_set); +} + +device_info_set device_info_set::of_instance(const std::wstring& instance_id) { + auto instance = of_empty(); + instance.add_instance(instance_id); + return instance; +} + +device_info_set device_info_set::of_path(const std::wstring& device_path) { + auto instance = of_empty(); + instance.add_device_path(device_path); + return instance; +} + +device_info_set device_info_set::of_empty() { + auto dev_info_set = SetupDiCreateDeviceInfoList(nullptr, nullptr); + if (dev_info_set == INVALID_HANDLE_VALUE) + usb_error::throw_error("internal error (SetupDiCreateDeviceInfoList)"); + return device_info_set(dev_info_set); +} + +device_info_set::device_info_set(device_info_set&& info_set) noexcept + : dev_info_set_(info_set.dev_info_set_), dev_info_data_(info_set.dev_info_data_), + has_dev_intf_data_(info_set.has_dev_intf_data_), dev_intf_data_(info_set.dev_intf_data_), + iteration_index(info_set.iteration_index) { + info_set.dev_info_set_ = INVALID_HANDLE_VALUE; + info_set.has_dev_intf_data_ = false; +} + +device_info_set::~device_info_set() { + if (dev_info_set_ == INVALID_HANDLE_VALUE) + return; + + if (has_dev_intf_data_) + SetupDiDeleteDeviceInterfaceData(dev_info_set_, &dev_intf_data_); + SetupDiDestroyDeviceInfoList(dev_info_set_); +} + +void device_info_set::add_instance(const std::wstring& instance_id) { + if (SetupDiOpenDeviceInfoW(dev_info_set_, instance_id.c_str(), nullptr, 0, &dev_info_data_) == 0) + throw usb_error("internal error (SetupDiOpenDeviceInfoW)", GetLastError()); +} + +void device_info_set::add_device_path(const std::wstring& device_path) { + if (has_dev_intf_data_) + throw usb_error("calling add_device_path() multiple times is not implemented"); + + // load device information into dev info set + if (SetupDiOpenDeviceInterfaceW(dev_info_set_, device_path.c_str(), 0, &dev_intf_data_) == 0) + usb_error::throw_error("internal error (SetupDiOpenDeviceInterfaceW)"); + has_dev_intf_data_ = true; + + if (SetupDiGetDeviceInterfaceDetailW(dev_info_set_, &dev_intf_data_, nullptr, 0, nullptr, &dev_info_data_) == 0) { + auto err = GetLastError(); + if (err != ERROR_INSUFFICIENT_BUFFER) + throw usb_error("internal error (SetupDiGetDeviceInterfaceDetailW)", err); + } +} + +bool device_info_set::next() { + iteration_index += 1; + + if (SetupDiEnumDeviceInfo(dev_info_set_, iteration_index, &dev_info_data_) == 0) { + auto err = GetLastError(); + if (err == ERROR_NO_MORE_ITEMS) + return false; + throw usb_error("internal error (SetupDiEnumDeviceInfo)", err); + } + + return true; +} + + +uint32_t device_info_set::get_device_property_int(const DEVPROPKEY& prop_key) { + // query property value + DEVPROPTYPE property_type; + uint32_t property_value = -1; + if (!SetupDiGetDevicePropertyW(dev_info_set_, &dev_info_data_, &prop_key, &property_type, reinterpret_cast(&property_value), sizeof(property_value), nullptr, 0)) + usb_error::throw_error("internal error (SetupDiGetDevicePropertyW)"); + + // check property type + if (property_type != DEVPROP_TYPE_UINT32) + throw usb_error("internal error (SetupDiGetDevicePropertyW)"); + + return property_value; +} + +std::vector device_info_set::get_device_property_variable_length(const DEVPROPKEY& prop_key, DEVPROPTYPE expected_type) { + + // query length + DWORD required_size = 0; + DEVPROPTYPE property_type; + if (!SetupDiGetDevicePropertyW(dev_info_set_, &dev_info_data_, &prop_key, &property_type, nullptr, 0, &required_size, 0)) { + DWORD err = GetLastError(); + if (err == ERROR_NOT_FOUND) + return {}; + if (err != ERROR_INSUFFICIENT_BUFFER) + throw usb_error("internal error (SetupDiGetDevicePropertyW)", err); + } + + // check property type + if (property_type != expected_type) + throw usb_error("internal error (SetupDiGetDevicePropertyW)"); + + // query property value + std::vector property_value; + property_value.resize(required_size); + if (!SetupDiGetDevicePropertyW(dev_info_set_, &dev_info_data_, &prop_key, &property_type, &property_value[0], required_size, nullptr, 0)) + usb_error::throw_error("internal error (SetupDiGetDevicePropertyW)"); + + return property_value; +} + +std::wstring device_info_set::get_device_property_string(const DEVPROPKEY& prop_key) { + + auto property_value = get_device_property_variable_length(prop_key, DEVPROP_TYPE_STRING); + if (property_value.size() == 0) + return L""; + return std::wstring(reinterpret_cast(&property_value[0])); +} + +std::vector device_info_set::get_device_property_string_list(const DEVPROPKEY& prop_key) { + auto property_value = get_device_property_variable_length(prop_key, DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST); + if (property_value.size() == 0) + return {}; + return split_string_list(reinterpret_cast(&property_value[0])); +} + +std::vector device_info_set::split_string_list(const wchar_t* str_list_raw) { + std::vector str_list; + int offset = 0; + while (str_list_raw[offset] != L'\0') { + str_list.push_back(str_list_raw + offset); + offset += static_cast(str_list.back().length()) + 1; + } + + return str_list; +} + +bool device_info_set::is_composite_device() { + std::wstring device_service = get_device_property_string(DEVPKEY_Device_Service); + return lstrcmpiW(device_service.c_str(), L"usbccgp") == 0; +} + +std::wstring device_info_set::get_device_path(const std::wstring& instance_id, const GUID& interface_guid) { + + // get device info set for instance + HDEVINFO dev_info_set = SetupDiGetClassDevsW(&interface_guid, instance_id.c_str(), nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info_set == INVALID_HANDLE_VALUE) + usb_error::throw_error("internal error (SetupDiGetClassDevsW)"); + + // ensure the result is destroyed when the scope is left + auto dev_info_set_guard = make_scope_exit([dev_info_set]() { + SetupDiDestroyDeviceInfoList(dev_info_set); + }); + + // retrieve first element of enumeration + SP_DEVICE_INTERFACE_DATA dev_intf_data = { sizeof(dev_intf_data) }; + if (!SetupDiEnumDeviceInterfaces(dev_info_set, nullptr, &interface_guid, 0, &dev_intf_data)) + usb_error::throw_error("internal error (SetupDiEnumDeviceInterfaces)"); + + // retrieve path + uint8_t dev_path_buf[MAX_PATH * sizeof(WCHAR) + sizeof(DWORD)]; + memset(dev_path_buf, 0, sizeof(dev_path_buf)); + PSP_DEVICE_INTERFACE_DETAIL_DATA_W intf_detail_data = reinterpret_cast(dev_path_buf); + intf_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + if (!SetupDiGetDeviceInterfaceDetailW(dev_info_set, &dev_intf_data, intf_detail_data, sizeof(dev_path_buf), nullptr, nullptr)) + throw usb_error("Internal error (SetupDiGetDeviceInterfaceDetailA)", GetLastError()); + + return intf_detail_data->DevicePath; +} + +std::wstring device_info_set::get_device_path_by_guid(const std::wstring& instance_id) { + auto device_guids = find_device_interface_guids(); + + CLSID clsid{}; + // use GUIDs to get device path + for (const std::wstring& guid : device_guids) { + if (CLSIDFromString(guid.c_str(), &clsid) != NOERROR) + continue; + + try { + return get_device_path(instance_id.c_str(), clsid); + } + catch (usb_error&) { + // ignore and try next one + } + } + + return {}; +} + +std::vector device_info_set::find_device_interface_guids() { + HKEY reg_key = SetupDiOpenDevRegKey(dev_info_set_, &dev_info_data_, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (reg_key == INVALID_HANDLE_VALUE) + throw usb_error("Cannot open device registry key", GetLastError()); + + auto reg_key_guard = make_scope_exit([reg_key]() { + RegCloseKey(reg_key); + }); + + // read registry value (without buffer, to query length) + DWORD value_type = 0; + DWORD value_size = 0; + LSTATUS res = RegQueryValueExW(reg_key, L"DeviceInterfaceGUIDs", nullptr, &value_type, nullptr, &value_size); + if (res == ERROR_FILE_NOT_FOUND) + return std::vector(); + if (res != 0 && res != ERROR_MORE_DATA) + throw usb_error("Internal error (RegQueryValueExW)", res); + + std::vector str_list_raw; + str_list_raw.resize(value_size); + + // read registry value (with buffer) + res = RegQueryValueExW(reg_key, L"DeviceInterfaceGUIDs", nullptr, &value_type, &str_list_raw[0], &value_size); + if (res != 0) + throw usb_error("Internal error (RegQueryValueExW)", res); + + return split_string_list(reinterpret_cast(&str_list_raw[0])); +} diff --git a/reference/windows/USB/device_info_set.h b/reference/windows/USB/device_info_set.h new file mode 100644 index 00000000..60929951 --- /dev/null +++ b/reference/windows/USB/device_info_set.h @@ -0,0 +1,150 @@ +// +// Java Does USB +// Copyright (c) 2023 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// +// Reference C++ code for Windows +// + +#pragma once + +#include +#include +#include +#undef min +#undef max +#undef LowSpeed +#include + +/** + * Device information set (of Windows Setup API). + * + * An instance of this class represents a device information set (DEVINFO) + * and a current element within the set. + */ +class device_info_set +{ +public: + /** + * Creates a new device info set containing the present devices of the specified device class and + * optionally device instance ID. + * + * After creation, there is no current element. `next()` should be called to iterate the first + * and all subsequent elements. + * + * @param interface_guid device interface class GUID + * @param instance_id device instance ID + * @return device info set + */ + static device_info_set of_present_devices(const GUID& interface_guid, const std::wstring& instance_id = L""); + + /** + * Creates a new device info set containing a single device with the specified instance ID. + * + * The device becomes the current element. The set cannot be iterated. + * + * @param instance_id instance ID + * @return device info set + */ + static device_info_set of_instance(const std::wstring& instance_id); + + /** + * Creates a new device info set containing a single device with the specified path. + * + * The device becomes the current element. The set cannot be iterated. + * + * @param device_path device path + * @return device info set + */ + static device_info_set of_path(const std::wstring& device_path); + + /** + * Creates a new empty device info set. + * + * @return device info set + */ + static device_info_set of_empty(); + + /** + * Iterates to the next element in this set. + * + * @return `true` if there is a current element, `false` if the iteration moved beyond the last element + */ + bool next(); + + /** + * Gets the integer device property of the current element. + * + * @param prop_key property key (`DEVPKEY_xxx`) + * @return property value + */ + uint32_t get_device_property_int(const DEVPROPKEY& prop_key); + + /** + * Gets the string device property of the current element. + * + * @param prop_key property key (`DEVPKEY_xxx`) + * @return property value + */ + std::wstring get_device_property_string(const DEVPROPKEY& prop_key); + + /** + * Gets the string list device property of the current element. + * + * @param prop_key property key (`DEVPKEY_xxx`) + * @return property value + */ + std::vector get_device_property_string_list(const DEVPROPKEY& prop_key); + + /** + * Checks if the current element is a composite device. + * + * @return `true` if it is a composite device + */ + bool is_composite_device(); + + device_info_set(device_info_set&& info_set) noexcept; + ~device_info_set(); + + /** + * Gets the device path for the device with the given device instance ID and device interface class. + * + * @param instance_id device instance ID + * @param interface_guid device interface class GUID + * @return the device path + */ + static std::wstring get_device_path(const std::wstring& instance_id, const GUID& interface_guid); + + /** + * Gets the device path for the device with the given instance ID. + * + * The device path is looked up by checking the GUIDs associated with the current element. + * + * @param instance_id device instance ID + * @return the device path, `nullptr` if not found + */ + std::wstring get_device_path_by_guid(const std::wstring& instance_id); + +private: + device_info_set(HDEVINFO dev_info_set); + device_info_set() = delete; + device_info_set(const device_info_set& info_set) = delete; + device_info_set& operator=(const device_info_set&) = delete; + device_info_set& operator=(device_info_set&& info_set) = delete; + + void add_instance(const std::wstring& instance_id); + void add_device_path(const std::wstring& device_path); + std::vector find_device_interface_guids(); + + std::vector get_device_property_variable_length(const DEVPROPKEY& prop_key, DEVPROPTYPE expected_type); + static std::vector split_string_list(const wchar_t* str_list_raw); + + + HDEVINFO dev_info_set_; + SP_DEVINFO_DATA dev_info_data_; + bool has_dev_intf_data_; + SP_DEVICE_INTERFACE_DATA dev_intf_data_; + int iteration_index; +}; + diff --git a/reference/windows/USB/tests.cpp b/reference/windows/USB/tests.cpp index 894da2e1..54ac0169 100644 --- a/reference/windows/USB/tests.cpp +++ b/reference/windows/USB/tests.cpp @@ -43,15 +43,22 @@ void tests::run() { void tests::test_current_device() { try { std::cout << "Found test device" << std::endl; + + is_composite = test_device->product_id() == 0xcea0; + loopback_intf = is_composite ? 3 : 0; + loopback_ep_out = is_composite ? 1 : 1; + loopback_ep_in = is_composite ? 2 : 2; + test_device->open(); - test_device->claim_interface(0); + test_device->claim_interface(loopback_intf); test_control_transfers(); test_bulk_transfers(); test_speed(); - test_device->release_interface(0); + test_device->release_interface(loopback_intf); test_device->close(); + std::cout << "Test completed" << std::endl; } catch (const std::exception& e) { @@ -65,7 +72,7 @@ void tests::test_control_transfers() { usb_request_type::type_vendor, usb_request_type::recipient_interface); request_set_value_no_data.bRequest = 0x01; request_set_value_no_data.wValue = 0x9a41; - request_set_value_no_data.wIndex = 0; // interface number + request_set_value_no_data.wIndex = loopback_intf; request_set_value_no_data.wLength = 0; test_device->control_transfer(request_set_value_no_data); @@ -74,7 +81,7 @@ void tests::test_control_transfers() { usb_request_type::type_vendor, usb_request_type::recipient_interface); request_get_data.bRequest = 0x03; request_get_data.wValue = 0; - request_get_data.wIndex = 0; // interface number + request_get_data.wIndex = loopback_intf; request_get_data.wLength = 4; auto data = test_device->control_transfer_in(request_get_data); std::vector expected_data{ 0x41, 0x9a, 0x00, 0x00 }; @@ -86,14 +93,37 @@ void tests::test_control_transfers() { usb_request_type::type_vendor, usb_request_type::recipient_interface); request_set_value_data.bRequest = 0x02; request_set_value_data.wValue = 0; - request_set_value_data.wIndex = 0; // interface number + request_set_value_data.wIndex = loopback_intf; request_set_value_data.wLength = static_cast(sent_value.size()); test_device->control_transfer_out(request_set_value_data, sent_value); data = test_device->control_transfer_in(request_get_data); assert_equals(sent_value, data); + + test_control_transfer_intf(loopback_intf); + + if (is_composite) { + test_device->claim_interface(2); + test_control_transfer_intf(2); + test_device->release_interface(2); + } } +void tests::test_control_transfer_intf(int intf_num) { + usb_control_request request_get_intf_num = { 0 }; + request_get_intf_num.bmRequestType = usb_control_request::request_type(usb_request_type::direction_in, + usb_request_type::type_vendor, usb_request_type::recipient_interface); + request_get_intf_num.bRequest = 0x05; + request_get_intf_num.wValue = 0; + request_get_intf_num.wIndex = intf_num; + request_get_intf_num.wLength = 1; + auto data = test_device->control_transfer_in(request_get_intf_num); + + std::vector expected_data{ (uint8_t)intf_num }; + assert_equals(expected_data, data); +} + + void tests::test_bulk_transfers() { test_loopback(12); test_loopback(130); @@ -113,7 +143,7 @@ void tests::test_loopback(int num_bytes) { std::thread reader([this, &rx_data, num_bytes]() { size_t bytes_read = 0; while (bytes_read < num_bytes) { - auto data = test_device->transfer_in(2); + auto data = test_device->transfer_in(loopback_ep_in); rx_data.insert(rx_data.end(), data.begin(), data.end()); bytes_read += data.size(); } @@ -125,7 +155,7 @@ void tests::test_loopback(int num_bytes) { while (bytes_written < num_bytes) { int size = std::min(chunk_size, num_bytes - bytes_written); std::vector chunk = {random_data.begin() + bytes_written, random_data.begin() + bytes_written + size}; - test_device->transfer_out(1, chunk); + test_device->transfer_out(loopback_ep_out, chunk); bytes_written += size; } @@ -169,5 +199,6 @@ std::vector tests::random_bytes(int num) { } bool tests::is_test_device(usb_device_ptr device) { - return device->vendor_id() == 0xcafe && device->product_id() == 0xceaf; + return device->vendor_id() == 0xcafe + && (device->product_id() == 0xceaf || device->product_id() == 0xcea0); } diff --git a/reference/windows/USB/tests.hpp b/reference/windows/USB/tests.hpp index 11cf328f..dbcd0903 100644 --- a/reference/windows/USB/tests.hpp +++ b/reference/windows/USB/tests.hpp @@ -21,6 +21,7 @@ class tests { void test_control_transfers(); void test_bulk_transfers(); void test_speed(); + void test_control_transfer_intf(int intf_num); void test_loopback(int num_bytes); @@ -33,5 +34,9 @@ class tests { usb_device_ptr test_device; usb_registry registry; + bool is_composite; + int loopback_intf; + int loopback_ep_out; + int loopback_ep_in; }; diff --git a/reference/windows/USB/usb_device.cpp b/reference/windows/USB/usb_device.cpp index 436c23d2..bcb8b72f 100644 --- a/reference/windows/USB/usb_device.cpp +++ b/reference/windows/USB/usb_device.cpp @@ -10,21 +10,27 @@ #include "usb_device.hpp" #include "usb_error.hpp" #include "usb_iostream.hpp" +#include "device_info_set.h" #include "scope.hpp" #include "config_parser.hpp" #include "usb_registry.hpp" +#include + +#include #include +#include +#include -usb_device::usb_device(usb_registry* registry, std::wstring&& device_path, int vendor_id, int product_id, const std::vector& config_desc, std::map&& children) -: registry_(registry), vendor_id_(vendor_id), product_id_(product_id), is_open_(false), device_path_(std::move(device_path)) { +usb_device::usb_device(usb_registry* registry, std::wstring&& device_path, int vendor_id, int product_id, const std::vector& config_desc, bool is_composite) +: registry_(registry), vendor_id_(vendor_id), product_id_(product_id), is_open_(false), device_path_(std::move(device_path)), is_composite_(is_composite) { config_parser parser{}; parser.parse(config_desc.data(), static_cast(config_desc.size())); interfaces_ = std::move(parser.interfaces); functions_ = std::move(parser.functions); - build_handles(device_path_, std::move(children)); + build_handles(device_path_); } void usb_device::set_product_names(const std::string& manufacturer, const std::string& product, const std::string& serial_number) { @@ -33,19 +39,14 @@ void usb_device::set_product_names(const std::string& manufacturer, const std::s serial_number_ = serial_number; } -void usb_device::build_handles(const std::wstring& device_path, std::map&& children) { +void usb_device::build_handles(const std::wstring& device_path) { for (const usb_interface& intf : interfaces_) { int intf_number = intf.number(); auto function = get_function(intf_number); std::wstring path; - if (function->first_interface() == intf_number) { - if (children.size() > 0) { - path = std::move(children[intf_number]); - } else { - path = device_path; - } - } + if (intf_number == 0) + path = device_path; interface_handles_.push_back(interface_handle(intf_number, function->first_interface(), std::move(path))); } @@ -117,6 +118,26 @@ void usb_device::close() { } void usb_device::claim_interface(int interface_number) { + // When a device is plugged in, a notification is sent. For composite devices, it is a notification + // that the composite device is ready. Each composite function will be registered separately and + // the related information will be available with a delay. So for composite functions, several + // retries might be needed until the device path is available. + int num_retries = 30; // 30 x 100ms + while (true) { + if (try_claim_interface(interface_number)) + return; // success + + num_retries -= 1; + if (num_retries == 0) + throw usb_error("claiming interface failed (function has no device interface GUID/path, might be missing WinUSB driver)"); + + // sleep and retry + std::cerr << "Sleeping for 100ms..." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } +} + +bool usb_device::try_claim_interface(int interface_number) { if (!is_open()) throw usb_error("USB device is not open"); @@ -130,9 +151,16 @@ void usb_device::claim_interface(int interface_number) { interface_handle* intf_handle = get_interface_handle(interface_number); interface_handle* first_intf_handle = get_interface_handle(intf_handle->first_interface_num); - // open device if needed + // both the device and the first interface must be opened for any interface belonging to the same function if (first_intf_handle->device_handle == nullptr) { - first_intf_handle->device_handle = CreateFileW(first_intf_handle->device_path.c_str(), + auto device_path = get_interface_device_path(first_intf_handle->interface_num); + if (device_path.empty()) + return false; + + std::wcerr << "opening device " << device_path << std::endl; + + // open device + first_intf_handle->device_handle = CreateFileW(device_path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, @@ -140,23 +168,28 @@ void usb_device::claim_interface(int interface_number) { FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr); if (first_intf_handle->device_handle == INVALID_HANDLE_VALUE) - usb_error::throw_error("Cannot open USB device"); - - registry_->add_to_completion_port(first_intf_handle->device_handle); - } + usb_error::throw_error("failed to claim interface (cannot open USB device)"); - // open interface - if (!WinUsb_Initialize(first_intf_handle->device_handle, &intf_handle->intf_handle)) { - if (first_intf_handle->device_open_count == 0) { + // open first interface + if (!WinUsb_Initialize(first_intf_handle->device_handle, &first_intf_handle->winusb_handle)) { + auto err = GetLastError(); CloseHandle(first_intf_handle->device_handle); first_intf_handle->device_handle = nullptr; + throw usb_error("failed to claim interface (cannot open associated interface)", err); } - usb_error::throw_error("Cannot open USB device"); - return; + + registry_->add_to_completion_port(first_intf_handle->device_handle); + } + + // open associated interface + if (intf_handle != first_intf_handle) { + if (!WinUsb_GetAssociatedInterface(first_intf_handle->winusb_handle, intf_handle->interface_num - first_intf_handle->interface_num - 1, &intf_handle->winusb_handle)) + throw usb_error("cannot open associated interface", GetLastError()); } first_intf_handle->device_open_count += 1; intf->set_claimed(true); + return true; } void usb_device::release_interface(int interface_number) { @@ -173,14 +206,19 @@ void usb_device::release_interface(int interface_number) { interface_handle* intf_handle = get_interface_handle(interface_number); interface_handle* first_intf_handle = get_interface_handle(intf_handle->first_interface_num); - // close interface - WinUsb_Free(intf_handle->intf_handle); - intf_handle->intf_handle = nullptr; intf->set_claimed(false); + if (intf_handle != first_intf_handle) { + // close assicated interface + if (!WinUsb_Free(intf_handle->winusb_handle)) + throw usb_error("failed to release associated interface", GetLastError()); + intf_handle->winusb_handle = nullptr; + } + // close device if needed first_intf_handle->device_open_count -= 1; if (first_intf_handle->device_open_count == 0) { + WinUsb_Free(first_intf_handle->winusb_handle); CloseHandle(first_intf_handle->device_handle); first_intf_handle->device_handle = nullptr; } @@ -188,18 +226,18 @@ void usb_device::release_interface(int interface_number) { std::vector usb_device::transfer_in(int endpoint_number, int timeout) { - auto intf_handle = check_valid_endpoint(usb_direction::in, endpoint_number)->intf_handle; + auto winusb_handle = check_valid_endpoint(usb_direction::in, endpoint_number)->winusb_handle; UCHAR endpoint_address = ep_address(usb_direction::in, endpoint_number); auto endpoint = get_endpoint_ptr(usb_direction::in, endpoint_number); ULONG value = timeout; - if (!WinUsb_SetPipePolicy(intf_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) + if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) usb_error::throw_error("Failed to set endpoint timeout"); std::vector data(endpoint->packet_size()); DWORD len = 0; - if (!WinUsb_ReadPipe(intf_handle, endpoint_address, static_cast(data.data()), endpoint->packet_size(), &len, nullptr)) + if (!WinUsb_ReadPipe(winusb_handle, endpoint_address, static_cast(data.data()), endpoint->packet_size(), &len, nullptr)) usb_error::throw_error("Cannot receive from USB endpoint"); data.resize(len); @@ -210,15 +248,15 @@ void usb_device::transfer_out(int endpoint_number, const std::vector& d if (len < 0 || len > data.size()) len = static_cast(data.size()); - auto intf_handle = check_valid_endpoint(usb_direction::out, endpoint_number)->intf_handle; + auto winusb_handle = check_valid_endpoint(usb_direction::out, endpoint_number)->winusb_handle; UCHAR endpoint_address = ep_address(usb_direction::out, endpoint_number); ULONG value = timeout; - if (!WinUsb_SetPipePolicy(intf_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) + if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) usb_error::throw_error("Failed to set endpoint timeout"); DWORD tlen = 0; - if (!WinUsb_WritePipe(intf_handle, endpoint_address, const_cast(data.data()), len, &tlen, nullptr)) + if (!WinUsb_WritePipe(winusb_handle, endpoint_address, const_cast(data.data()), len, &tlen, nullptr)) usb_error::throw_error("Failed to transmit to USB endpoint"); } @@ -227,10 +265,10 @@ int usb_device::control_transfer_core(const usb_control_request &request, uint8_ if (!is_open()) throw usb_error("USB device is not open"); - auto handle = get_control_transfer_interface_handle(request)->intf_handle; + auto winusb_handle = get_control_transfer_interface_handle(request)->winusb_handle; ULONG value = timeout; - if (!WinUsb_SetPipePolicy(handle, 0, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) + if (!WinUsb_SetPipePolicy(winusb_handle, 0, PIPE_TRANSFER_TIMEOUT, sizeof(value), &value)) usb_error::throw_error("Failed to set endpoint timeout"); WINUSB_SETUP_PACKET setup_packet = { 0 }; @@ -241,7 +279,7 @@ int usb_device::control_transfer_core(const usb_control_request &request, uint8_ setup_packet.Length = request.wLength; DWORD len = 0; - if (!WinUsb_ControlTransfer(handle, setup_packet, data, request.wLength, &len, nullptr)) + if (!WinUsb_ControlTransfer(winusb_handle, setup_packet, data, request.wLength, &len, nullptr)) usb_error::throw_error("Control transfer failed"); return len; @@ -395,41 +433,41 @@ void usb_device::remove_completion_handler(OVERLAPPED* overlapped) { } void usb_device::configure_for_async_io(usb_direction direction, int endpoint_number) { - auto intf_handle = check_valid_endpoint(direction, endpoint_number)->intf_handle; + auto winusb_handle = check_valid_endpoint(direction, endpoint_number)->winusb_handle; UCHAR endpoint_address = ep_address(direction, endpoint_number); ULONG timeout = 0; - if (!WinUsb_SetPipePolicy(intf_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) + if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) usb_error::throw_error("Failed to set endpoint timeout"); UCHAR raw_io = 1; - if (!WinUsb_SetPipePolicy(intf_handle, endpoint_address, RAW_IO, sizeof(raw_io), &raw_io)) + if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address, RAW_IO, sizeof(raw_io), &raw_io)) usb_error::throw_error("Failed to set endpoint for raw IO"); } void usb_device::submit_transfer_in(int endpoint_number, uint8_t* buffer, int buffer_len, OVERLAPPED* overlapped) { - auto intf_handle = check_valid_endpoint(usb_direction::in, endpoint_number)->intf_handle; + auto winusb_handle = check_valid_endpoint(usb_direction::in, endpoint_number)->winusb_handle; UCHAR endpoint_address = ep_address(usb_direction::in, endpoint_number); - if (!WinUsb_ReadPipe(intf_handle, endpoint_address, buffer, buffer_len, nullptr, overlapped)) { + if (!WinUsb_ReadPipe(winusb_handle, endpoint_address, buffer, buffer_len, nullptr, overlapped)) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) return; - throw new usb_error("Failed to submit transfer IN", err); + throw usb_error("Failed to submit transfer IN", err); } } void usb_device::submit_transfer_out(int endpoint_number, uint8_t* data, int data_len, OVERLAPPED* overlapped) { - auto intf_handle = check_valid_endpoint(usb_direction::out, endpoint_number)->intf_handle; + auto winusb_handle = check_valid_endpoint(usb_direction::out, endpoint_number)->winusb_handle; UCHAR endpoint_address = ep_address(usb_direction::out, endpoint_number); - if (!WinUsb_WritePipe(intf_handle, endpoint_address, data, data_len, nullptr, overlapped)) { + if (!WinUsb_WritePipe(winusb_handle, endpoint_address, data, data_len, nullptr, overlapped)) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) return; - throw new usb_error("Failed to submit transfer OUT", err); + throw usb_error("Failed to submit transfer OUT", err); } } @@ -440,9 +478,83 @@ void usb_device::cancel_transfer(usb_direction direction, int endpoint_number, O usb_error::throw_error("Error on cancelling transfer"); } +std::wstring usb_device::get_interface_device_path(int interface_num) { + if (!is_composite_) + return device_path_; + + auto it = interface_device_paths_.find(interface_num); + if (it != interface_device_paths_.end()) + return it->second; + + auto dev_info_set = device_info_set::of_path(device_path_); + + auto children_instance_ids = dev_info_set.get_device_property_string_list(DEVPKEY_Device_Children); + + std::wcerr << "children IDs: "; + for (auto it = children_instance_ids.begin(); it < children_instance_ids.end(); it++) { + if (it != children_instance_ids.begin()) + std::wcerr << ", "; + std::wcerr << *it; + } + std::wcerr << std::endl; + + std::wstring child_path; + for (auto& child_id : children_instance_ids) { + child_path = get_child_device_path(child_id, interface_num); + if (!child_path.empty()) + return child_path; + } + + return {}; // retry later +} + +std::wstring usb_device::get_child_device_path(const std::wstring& child_id, int interface_num) { + + auto dev_info_set = device_info_set::of_instance(child_id); + + auto hardware_ids = dev_info_set.get_device_property_string_list(DEVPKEY_Device_HardwareIds); + if (hardware_ids.empty()) { + std::wcerr << "child device " << child_id << " has no hardware IDs" << std::endl; + return {}; // continue with next child + } + + auto intf_num = extract_interface_number(hardware_ids); + if (intf_num == -1) { + std::wcerr << "child device " << child_id << " has no interface number" << std::endl; + return {}; // continue with next child + } + + if (intf_num != interface_num) + return {}; // continue with next child + + auto device_path = dev_info_set.get_device_path_by_guid(child_id); + if (device_path.empty()) { + std::wcerr << "child device " << child_id << " has no device path" << std::endl; + throw usb_error("claiming interface failed (function has no device interface GUID/path, might be missing WinUSB driver)"); + } + + std::wcerr << "child device: interface=" << intf_num << ", device path=" << device_path << std::endl; + interface_device_paths_[interface_num] = device_path; + return device_path; // success +} + +static const std::wregex multiple_interface_id_pattern(L"USB\\\\VID_[0-9A-Fa-f]{4}&PID_[0-9A-Fa-f]{4}&MI_([0-9A-Fa-f]{2})"); + +int usb_device::extract_interface_number(const std::vector& hardware_ids) { + // Also see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices + + for (auto& id : hardware_ids) { + auto matches = std::wsmatch{}; + if (std::regex_search(id, matches, multiple_interface_id_pattern)) + return std::stoul(matches[1].str(), nullptr, 16); + } + + return -1; +} + // --- interface_handle usb_device::interface_handle::interface_handle(int intf_num, int first_num, std::wstring&& path) - : interface_num(intf_num), first_interface_num(first_num), device_path(std::move(path)), - device_handle(nullptr), intf_handle(nullptr), device_open_count(0) { } + : interface_num(intf_num), first_interface_num(first_num), + device_handle(nullptr), winusb_handle(nullptr), device_open_count(0) { } diff --git a/reference/windows/USB/usb_device.hpp b/reference/windows/USB/usb_device.hpp index e4168021..6f5760c5 100644 --- a/reference/windows/USB/usb_device.hpp +++ b/reference/windows/USB/usb_device.hpp @@ -241,17 +241,20 @@ class usb_device { struct interface_handle { int interface_num; int first_interface_num; - std::wstring device_path; HANDLE device_handle; - WINUSB_INTERFACE_HANDLE intf_handle; + WINUSB_INTERFACE_HANDLE winusb_handle; int device_open_count; interface_handle(int intf_num, int first_num, std::wstring&& path); }; - usb_device(usb_registry* registry, std::wstring&& device_path, int vendor_id, int product_id, const std::vector& config_desc, std::map&& children); + usb_device(usb_registry* registry, std::wstring&& device_path, int vendor_id, int product_id, const std::vector& config_desc, bool is_composite); void set_product_names(const std::string& manufacturer, const std::string& product, const std::string& serial_number); - void build_handles(const std::wstring& device_path, std::map&& children); + void build_handles(const std::wstring& device_path); + bool try_claim_interface(int interface_number); + std::wstring get_interface_device_path(int interface_num); + std::wstring get_child_device_path(const std::wstring& child_id, int interface_num); + static int extract_interface_number(const std::vector& hardware_ids); int control_transfer_core(const usb_control_request& request, uint8_t* data, int timeout); usb_composite_function* get_function(int intf_number); @@ -283,9 +286,11 @@ class usb_device { std::string product_; std::string serial_number_; + bool is_composite_; std::vector interfaces_; std::vector functions_; std::vector interface_handles_; + std::map interface_device_paths_; friend class usb_registry; friend class usb_istreambuf; diff --git a/reference/windows/USB/usb_device_info.cpp b/reference/windows/USB/usb_device_info.cpp deleted file mode 100644 index 1a4f9909..00000000 --- a/reference/windows/USB/usb_device_info.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -// Reference C++ code for Windows -// - -#include "usb_device_info.hpp" -#include "scope.hpp" -#include "usb_error.hpp" -#include -#include -#include -#include - - -std::wstring usb_device_info::get_device_path(const std::wstring& instance_id, const GUID* interface_guid) { - - // get device info set for instance - HDEVINFO dev_info_set = SetupDiGetClassDevsW(interface_guid, instance_id.c_str(), nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (dev_info_set == INVALID_HANDLE_VALUE) - usb_error::throw_error("internal error (SetupDiGetClassDevsW)"); - - // ensure the result is destroyed when the scope is left - auto dev_info_set_guard = make_scope_exit([dev_info_set]() { - SetupDiDestroyDeviceInfoList(dev_info_set); - }); - - // retrieve first element of enumeration - SP_DEVICE_INTERFACE_DATA dev_intf_data = { sizeof(dev_intf_data) }; - if (!SetupDiEnumDeviceInterfaces(dev_info_set, nullptr, interface_guid, 0, &dev_intf_data)) - usb_error::throw_error("internal error (SetupDiEnumDeviceInterfaces)"); - - // retrieve path - uint8_t dev_path_buf[MAX_PATH * sizeof(WCHAR) + sizeof(DWORD)]; - memset(dev_path_buf, 0, sizeof(dev_path_buf)); - PSP_DEVICE_INTERFACE_DETAIL_DATA_W intf_detail_data = reinterpret_cast(dev_path_buf); - intf_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); - if (!SetupDiGetDeviceInterfaceDetailW(dev_info_set, &dev_intf_data, intf_detail_data, sizeof(dev_path_buf), nullptr, nullptr)) - throw usb_error("Internal error (SetupDiGetDeviceInterfaceDetailA)", GetLastError()); - - return intf_detail_data->DevicePath; -} - -uint32_t usb_device_info::get_device_property_int(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key) { - // query property value - DEVPROPTYPE property_type; - uint32_t property_value = -1; - if (!SetupDiGetDevicePropertyW(dev_info_set, dev_info_data, prop_key, &property_type, reinterpret_cast(&property_value), sizeof(property_value), nullptr, 0)) - usb_error::throw_error("internal error (SetupDiGetDevicePropertyW)"); - - // check property type - if (property_type != DEVPROP_TYPE_UINT32) - throw usb_error("internal error (SetupDiGetDevicePropertyW)"); - - return property_value; -} - -std::vector usb_device_info::get_device_property_variable_length(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key, DEVPROPTYPE expected_type) { - - // query length - DWORD required_size = 0; - DEVPROPTYPE property_type; - if (!SetupDiGetDevicePropertyW(dev_info_set, dev_info_data, prop_key, &property_type, nullptr, 0, &required_size, 0)) { - DWORD err = GetLastError(); - if (err == ERROR_NOT_FOUND) - return {}; - if (err != ERROR_INSUFFICIENT_BUFFER) - throw usb_error("internal error (SetupDiGetDevicePropertyW)", err); - } - - // check property type - if (property_type != expected_type) - throw usb_error("internal error (SetupDiGetDevicePropertyW)"); - - // query property value - std::vector property_value; - property_value.resize(required_size); - if (!SetupDiGetDevicePropertyW(dev_info_set, dev_info_data, prop_key, &property_type, &property_value[0], required_size, nullptr, 0)) - usb_error::throw_error("internal error (SetupDiGetDevicePropertyW)"); - - return property_value; -} - -std::wstring usb_device_info::get_device_property_string(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key) { - - auto property_value = get_device_property_variable_length(dev_info_set, dev_info_data, prop_key, DEVPROP_TYPE_STRING); - if (property_value.size() == 0) - return L""; - return std::wstring(reinterpret_cast(&property_value[0])); -} - -std::vector usb_device_info::get_device_property_string_list(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key) { - auto property_value = get_device_property_variable_length(dev_info_set, dev_info_data, prop_key, DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST); - if (property_value.size() == 0) - return {}; - return split_string_list(reinterpret_cast(&property_value[0])); -} - -std::vector usb_device_info::split_string_list(const wchar_t* str_list_raw) { - std::vector str_list; - int offset = 0; - while (str_list_raw[offset] != L'\0') { - str_list.push_back(str_list_raw + offset); - offset += static_cast(str_list.back().length()) + 1; - } - - return str_list; -} - -std::vector usb_device_info::get_descriptor(HANDLE hub_handle, ULONG usb_port_num, uint16_t descriptor_type, int index, int language_id, int request_size) { - int size = sizeof(USB_DESCRIPTOR_REQUEST) + (request_size != 0 ? request_size : 255); - uint8_t* descriptor_request_buffer = new uint8_t[size]; - auto dev_info_set_guard = make_scope_exit([descriptor_request_buffer]() { - delete[] descriptor_request_buffer; - }); - - // setup request data structure - USB_DESCRIPTOR_REQUEST* descriptor_request = reinterpret_cast(descriptor_request_buffer); - descriptor_request->ConnectionIndex = usb_port_num; - descriptor_request->SetupPacket.bmRequest = 0x80; // device-to-host / type standard / recipient device - descriptor_request->SetupPacket.bRequest = 0x06; // GET_DESCRIPTOR - descriptor_request->SetupPacket.wValue = (descriptor_type << 8) | index; - descriptor_request->SetupPacket.wIndex = language_id; - descriptor_request->SetupPacket.wLength = static_cast(size - sizeof(USB_DESCRIPTOR_REQUEST)); - - // get descriptor - DWORD bytesReturned = 0; - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, descriptor_request, size, descriptor_request, size, &bytesReturned, nullptr)) - throw usb_error("Cannot retrieve descriptor (DeviceIoControl)", GetLastError()); - int data_size = bytesReturned - sizeof(USB_DESCRIPTOR_REQUEST); - - if (data_size <= 2) - throw usb_error("invalid descriptor"); - - // determine expected size of descriptor - int expected_size; - if (descriptor_type != USB_CONFIGURATION_DESCRIPTOR_TYPE) { - expected_size = descriptor_request->Data[0]; - } - else { - auto config_desc = reinterpret_cast(descriptor_request->Data); - expected_size = config_desc->wTotalLength; - } - - // check against effective size - if (data_size < expected_size) { - if (request_size != 0) - throw usb_error("Unexpected descriptor size"); - - // repeat with larger size - return get_descriptor(hub_handle, usb_port_num, descriptor_type, index, language_id, expected_size); - } - - return std::vector(descriptor_request->Data, descriptor_request->Data + data_size); -} - -std::string usb_device_info::get_string(HANDLE hub_handle, ULONG usb_port_num, int index) { - if (index == 0) - return ""; - - std::vector str_desc_raw = get_descriptor(hub_handle, usb_port_num, USB_STRING_DESCRIPTOR_TYPE, index, 0x0409); - USB_STRING_DESCRIPTOR* str_desc = reinterpret_cast(str_desc_raw.data()); - - // required length of UTF-8 string - int len = WideCharToMultiByte(CP_UTF8, 0, str_desc->bString, str_desc->bLength / 2 - 1, nullptr, 0, nullptr, nullptr); - - // convert to UTF-8 - std::string result; - result.resize(len, 'x'); - WideCharToMultiByte(CP_UTF8, 0, str_desc->bString, str_desc->bLength / 2 - 1, &result[0], len, nullptr, nullptr); - return result; -} - -bool usb_device_info::is_composite_device(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data) { - std::wstring device_service = usb_device_info::get_device_property_string(dev_info_set, dev_info_data, &DEVPKEY_Device_Service); - return lstrcmpiW(device_service.c_str(), L"usbccgp") == 0; -} - -static const std::wregex multiple_interface_pattern(L"USB\\\\VID_[0-9A-Fa-f]{4}&PID_[0-9A-Fa-f]{4}&MI_([0-9A-Fa-f]{2})"); - -int usb_device_info::get_first_interface(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data) { - // Also see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices - - auto hardware_ids = usb_device_info::get_device_property_string_list(dev_info_set, dev_info_data, &DEVPKEY_Device_HardwareIds); - - for (const std::wstring& id : hardware_ids) { - auto matches = std::wsmatch{}; - if (std::regex_search(id, matches, multiple_interface_pattern)) - return std::stoul(matches[1].str(), nullptr, 16); - } - - return -1; -} - -std::vector usb_device_info::find_device_interface_guids(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data) { - HKEY reg_key = SetupDiOpenDevRegKey(dev_info_set, dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (reg_key == INVALID_HANDLE_VALUE) - throw usb_error("Cannot open device registry key", GetLastError()); - - auto reg_key_guard = make_scope_exit([reg_key]() { - RegCloseKey(reg_key); - }); - - // read registry value (without buffer, to query length) - DWORD value_type = 0; - DWORD value_size = 0; - LSTATUS res = RegQueryValueExW(reg_key, L"DeviceInterfaceGUIDs", nullptr, &value_type, nullptr, &value_size); - if (res == ERROR_FILE_NOT_FOUND) - return std::vector(); - if (res != 0 && res != ERROR_MORE_DATA) - throw usb_error("Internal error (RegQueryValueExW)", res); - - std::vector str_list_raw; - str_list_raw.resize(value_size); - - // read registry value (with buffer) - res = RegQueryValueExW(reg_key, L"DeviceInterfaceGUIDs", nullptr, &value_type, &str_list_raw[0], &value_size); - if (res != 0) - throw usb_error("Internal error (RegQueryValueExW)", res); - - return split_string_list(reinterpret_cast(&str_list_raw[0])); -} diff --git a/reference/windows/USB/usb_device_info.hpp b/reference/windows/USB/usb_device_info.hpp deleted file mode 100644 index 5f5ab067..00000000 --- a/reference/windows/USB/usb_device_info.hpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Java Does USB -// Copyright (c) 2022 Manuel Bleichenbacher -// Licensed under MIT License -// https://opensource.org/licenses/MIT -// -// Reference C++ code for Windows -// - -#pragma once - -#include -#include -#include -#undef min -#undef max -#undef LowSpeed -#include - -/// -/// Helper class for querying device information. -/// -class usb_device_info -{ -private: - /// - /// Get a device property of integer type. - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// property key - /// property integer value - static uint32_t get_device_property_int(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key); - - /// - /// Get a device property of string type. - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// property key - /// property string value - static std::wstring get_device_property_string(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key); - - /// - /// Get a device property of variable length. - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// property key - /// expected property type (use DEVPROP_TYPE_xxx constants) - /// property value as byte array - static std::vector get_device_property_variable_length(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key, DEVPROPTYPE expected_type); - - /// - /// Get a device property of string list type. - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// property key - /// property value as vector of strings - static std::vector get_device_property_string_list(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data, const DEVPROPKEY* prop_key); - - /// - /// Split the string list into a vector of strings - /// - /// The provides string list is a concatenation of null-terminated string, terminated with an additional zero-length string. - /// - /// - /// string list - /// vector of strings - static std::vector split_string_list(const wchar_t* string_list); - - /// - /// Get device path for the specified device instance and device interface class. - /// - /// device instance ID - /// device interface class GUID - /// device path - static std::wstring get_device_path(const std::wstring& instance_id, const GUID* interface_guid); - - /// - /// Get a USB descriptor. - /// - /// The descriptor is retrieved via the USB hub (the USB device's parent) so it can be - /// access for USB devices that are already opened by another application. - /// - /// - /// handle of USB hub - /// device's port number (at hub) - /// descriptor type (use USB_xxx_DESCRIPTOR_TYPE constants) - /// descriptor index - /// language ID - /// intial size to request - /// descriptor as byte array - static std::vector get_descriptor(HANDLE hub_handle, ULONG usb_port_num, uint16_t descriptor_type, int index, int language_id, int request_size = 0); - - /// - /// Get USB string with the specified index. - /// - /// The string descriptor is retrieved via the USB hub (the USB device's parent) so it can be - /// access for USB devices that are already opened by another application. - /// - /// - /// For string index 0, an empty string is returned. - /// - /// - /// handle of USB hub - /// device's port number (at hub) - /// string index - /// string - static std::string get_string(HANDLE hub_handle, ULONG usb_port_num, int index); - - /// - /// Query if device is a composite USB device. - /// - /// A composite device consists of multiple interfaces appearing as separate devices - /// in Windows. In the Setup API, they are represented as child devices. - /// - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// true if device is a composite device, false otherwise - static bool is_composite_device(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data); - - /// - /// Get the number of the first USB interface. - /// - /// The first interface number is relevant for child devices of composite devices. - /// - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// - static int get_first_interface(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data); - - /// - /// Get the device's interface GUIDs. - /// - /// handle of device information set containing the device - /// pointer to device information structure representing the device - /// vector of GUIDs - static std::vector find_device_interface_guids(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data); - - friend class usb_registry; -}; - diff --git a/reference/windows/USB/usb_error.cpp b/reference/windows/USB/usb_error.cpp index c57e0a8b..2c5da8e4 100644 --- a/reference/windows/USB/usb_error.cpp +++ b/reference/windows/USB/usb_error.cpp @@ -36,7 +36,7 @@ std::string usb_error::full_message(const char* message, int code) { LPSTR messageBuffer = nullptr; size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, code, 0, (LPSTR)&messageBuffer, 0, NULL); + nullptr, code, 0, (LPSTR)&messageBuffer, 0, nullptr); while (size > 0 && (messageBuffer[size - 1] == L'\r' || messageBuffer[size - 1] == '\n')) size--; diff --git a/reference/windows/USB/usb_iostream.cpp b/reference/windows/USB/usb_iostream.cpp index 20cb36d1..5d98701a 100644 --- a/reference/windows/USB/usb_iostream.cpp +++ b/reference/windows/USB/usb_iostream.cpp @@ -93,7 +93,7 @@ usb_istreambuf::int_type usb_istreambuf::underflow() { current_request = wait_for_request_completion(); if (current_request->result_code() != S_OK) - throw new usb_error("transfer IN failed", current_request->result_code()); + throw usb_error("transfer IN failed", current_request->result_code()); char* buf = reinterpret_cast(current_request->buffer); int size = current_request->result_size(); @@ -203,7 +203,7 @@ usb_ostreambuf::transfer_request* usb_ostreambuf::wait_for_available_transfer() // check for error DWORD result = request->result_code(); if (result != S_OK) - throw new usb_error("transfer OUT failed", result); + throw usb_error("transfer OUT failed", result); return request; } diff --git a/reference/windows/USB/usb_registry.cpp b/reference/windows/USB/usb_registry.cpp index bd64dd19..309c6390 100644 --- a/reference/windows/USB/usb_registry.cpp +++ b/reference/windows/USB/usb_registry.cpp @@ -9,7 +9,7 @@ #include "usb_registry.hpp" #include "usb_device.hpp" -#include "usb_device_info.hpp" +#include "device_info_set.h" #include "usb_error.hpp" #include "scope.hpp" @@ -26,7 +26,6 @@ #pragma comment (lib, "SetupAPI.lib") #pragma comment (lib, "Winusb.lib") - usb_registry::usb_registry() : on_connected_callback(nullptr), on_disconnected_callback(nullptr), is_device_list_ready(false), monitor_thread_id_(0), message_window(nullptr), @@ -107,7 +106,7 @@ void usb_registry::monitor() { notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; HDEVNOTIFY notify_handle = RegisterDeviceNotificationW(message_window, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE /* | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES */); - if (notify_handle == NULL) + if (notify_handle == nullptr) usb_error::throw_error("internal error (RegisterDeviceNotificationW)"); auto notify_handle_guard = make_scope_exit([notify_handle]() { UnregisterDeviceNotification(notify_handle); }); @@ -125,56 +124,53 @@ void usb_registry::monitor() { void usb_registry::detect_present_devices() { - // get device information set of all USB devices present - HDEVINFO dev_info_set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (dev_info_set == INVALID_HANDLE_VALUE) - throw usb_error("internal error (SetupDiGetClassDevsA)", GetLastError()); + // get device information set of all present USB devices + auto dev_info_set = device_info_set::of_present_devices(GUID_DEVINTERFACE_USB_DEVICE); - // ensure the result id destroyed when the scope is left - auto dev_info_set_guard = make_scope_exit([dev_info_set]() { - SetupDiDestroyDeviceInfoList(dev_info_set); - }); + std::map hub_handles{}; - SP_DEVINFO_DATA dev_info_data = { sizeof(dev_info_data) }; + auto hub_handle_guard = make_scope_exit([&hub_handles]() { + for (auto& hub : hub_handles) + CloseHandle(hub.second); + }); // iterate over the set - for (int i = 0; ; i++) { - if (!SetupDiEnumDeviceInfo(dev_info_set, i, &dev_info_data)) { - DWORD err = GetLastError(); - if (err == ERROR_NO_MORE_ITEMS) - break; - throw usb_error("Internal error (SetupDiEnumDeviceInfo)", err); - } + while (dev_info_set.next()) { + + auto instance_id = dev_info_set.get_device_property_string(DEVPKEY_Device_InstanceId); + auto device_path = device_info_set::get_device_path(instance_id, GUID_DEVINTERFACE_USB_DEVICE); + + std::wcerr << "Device present: InstanceId=" << instance_id << ", DevicePath=" << device_path << std::endl; // create new device - auto device = create_device(dev_info_set, &dev_info_data); + auto device = create_device_from_device_info(dev_info_set, std::move(device_path), hub_handles); devices.push_back(device); } } -std::shared_ptr usb_registry::create_device(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info_data) { +std::shared_ptr usb_registry::create_device_from_device_info(device_info_set& dev_info_set, std::wstring&& device_path, std::map& hub_handles) { - DWORD usb_port_num = usb_device_info::get_device_property_int(dev_info_set, dev_info_data, &DEVPKEY_Device_Address); - std::wstring instance_id = usb_device_info::get_device_property_string(dev_info_set, dev_info_data, &DEVPKEY_Device_InstanceId); - std::wstring parent_instance_id = usb_device_info::get_device_property_string(dev_info_set, dev_info_data, &DEVPKEY_Device_Parent); + DWORD usb_port_num = dev_info_set.get_device_property_int(DEVPKEY_Device_Address); + std::wstring parent_instance_id = dev_info_set.get_device_property_string(DEVPKEY_Device_Parent); + std::wstring hub_path = device_info_set::get_device_path(parent_instance_id, GUID_DEVINTERFACE_USB_HUB); - std::wstring hub_path = usb_device_info::get_device_path(parent_instance_id, &GUID_DEVINTERFACE_USB_HUB); - - // open parent (hub) - HANDLE hub_handle = CreateFileW(hub_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); - if (hub_handle == INVALID_HANDLE_VALUE) - usb_error::throw_error("Cannot open USB hub"); - - auto hub_handle_guard = make_scope_exit([hub_handle]() { - CloseHandle(hub_handle); - }); + // open parent (hub) if not open + HANDLE hub_handle; + auto it = hub_handles.find(hub_path); + if (it != hub_handles.end()) { + hub_handle = it->second; + } + else { + hub_handle = CreateFileW(hub_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); + if (hub_handle == INVALID_HANDLE_VALUE) + usb_error::throw_error("Cannot open USB hub"); + hub_handles[hub_path] = hub_handle; + } - // check for composite device - std::map children{}; - if (usb_device_info::is_composite_device(dev_info_set, dev_info_data)) - children = enumerate_child_devices(usb_device_info::get_device_property_string_list(dev_info_set, dev_info_data, &DEVPKEY_Device_Children)); + return create_device(std::move(device_path), dev_info_set.is_composite_device(), hub_handle, usb_port_num); +} - auto path = usb_device_info::get_device_path(instance_id, &GUID_DEVINTERFACE_USB_DEVICE); +std::shared_ptr usb_registry::create_device(std::wstring&& device_path, bool is_composite, HANDLE hub_handle, DWORD usb_port_num) { // get device descriptor USB_NODE_CONNECTION_INFORMATION_EX conn_info = { 0 }; @@ -183,67 +179,22 @@ std::shared_ptr usb_registry::create_device(HDEVINFO dev_info_set, S if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), &conn_info, sizeof(conn_info), &size, nullptr)) usb_error::throw_error("Internal error (cannot get device descriptor)"); + int vendorId = conn_info.DeviceDescriptor.idVendor; + int productId = conn_info.DeviceDescriptor.idProduct; + // get configuration descriptor - auto config_desc = usb_device_info::get_descriptor(hub_handle, usb_port_num, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0); + auto config_desc = get_descriptor(hub_handle, usb_port_num, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0); // Create new device - std::shared_ptr device(new usb_device(this, std::move(path), conn_info.DeviceDescriptor.idVendor, conn_info.DeviceDescriptor.idProduct, config_desc, std::move(children))); + std::shared_ptr device(new usb_device(this, std::move(device_path), vendorId, productId, config_desc, is_composite)); device->set_product_names( - usb_device_info::get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iManufacturer), - usb_device_info::get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iProduct), - usb_device_info::get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iSerialNumber) + get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iManufacturer), + get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iProduct), + get_string(hub_handle, usb_port_num, conn_info.DeviceDescriptor.iSerialNumber) ); return device; } -std::map usb_registry::enumerate_child_devices(const std::vector child_ids) { - - std::map children{}; - - for (const std::wstring& child_instance_id : child_ids) { - HDEVINFO dev_info_set = SetupDiCreateDeviceInfoList(NULL, NULL); - if (dev_info_set == INVALID_HANDLE_VALUE) - throw usb_error("internal error (SetupDiCreateDeviceInfoList)", GetLastError()); - - // ensure the result id destroyed when the scope is left - auto dev_info_set_guard = make_scope_exit([dev_info_set]() { - SetupDiDestroyDeviceInfoList(dev_info_set); - }); - - // get device info for child - SP_DEVINFO_DATA dev_info_data = { sizeof(dev_info_data) }; - if (!SetupDiOpenDeviceInfoW(dev_info_set, child_instance_id.c_str(), nullptr, 0, &dev_info_data)) - throw usb_error("internal error (SetupDiOpenDeviceInfoW)", GetLastError()); - - // get first interface number - int interface_number = usb_device_info::get_first_interface(dev_info_set, &dev_info_data); - if (interface_number == -1) - continue; - - // get device interface GUIDs - auto device_guids = usb_device_info::find_device_interface_guids(dev_info_set, &dev_info_data); - - CLSID clsid{}; - // use GUIDs to get device path - for (const std::wstring& guid : device_guids) { - if (CLSIDFromString(guid.c_str(), &clsid) != NOERROR) - continue; - - try { - auto device_path = usb_device_info::get_device_path(child_instance_id.c_str(), &clsid); - children[interface_number] = device_path; - break; - - } catch (usb_error&) { - // ignore and try next one - } - } - } - - return children; -} - - LRESULT usb_registry::handle_windows_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { usb_registry* self = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); @@ -253,19 +204,19 @@ LRESULT usb_registry::handle_windows_message(HWND hWnd, UINT uMsg, WPARAM wParam CREATESTRUCT* cs = reinterpret_cast(lParam); self = reinterpret_cast(cs->lpCreateParams); SetLastError(ERROR_SUCCESS); - LONG_PTR result = SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(self)); + LONG_PTR result = SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast(self)); break; } case WM_DESTROY: { - LONG_PTR result = SetWindowLongPtr(hWnd, GWLP_USERDATA, NULL); + LONG_PTR result = SetWindowLongPtrW(hWnd, GWLP_USERDATA, NULL); PostQuitMessage(0); break; } } if (self != nullptr && self->handle_message(hWnd, uMsg, wParam, lParam)) - return NULL; + return 0; return DefWindowProcW(hWnd, uMsg, wParam, lParam); } @@ -281,8 +232,10 @@ bool usb_registry::handle_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP DEV_BROADCAST_DEVICEINTERFACE_W* broadcast = reinterpret_cast(lParam); if (wParam == DBT_DEVICEARRIVAL) { + std::wcerr << "Device added: DevicePath=" << broadcast->dbcc_name << std::endl; on_device_connected(broadcast->dbcc_name); } else { + std::wcerr << "Device removed: DevicePath=" << broadcast->dbcc_name << std::endl; on_device_disconnected(broadcast->dbcc_name); } return true; @@ -292,35 +245,17 @@ void usb_registry::on_device_connected(const WCHAR* path) { usb_device_ptr device; try { - // create empty device information set - HDEVINFO dev_info_set = SetupDiCreateDeviceInfoList(NULL, NULL); - if (dev_info_set == INVALID_HANDLE_VALUE) - throw usb_error("internal error (SetupDiCreateDeviceInfoList)", GetLastError()); - - // ensure the result is destroyed when the scope is left - auto dev_info_set_guard = make_scope_exit([dev_info_set]() { - SetupDiDestroyDeviceInfoList(dev_info_set); - }); - - // load device information into dev info set - SP_DEVICE_INTERFACE_DATA dev_intf_data = { sizeof(dev_intf_data) }; - if (!SetupDiOpenDeviceInterfaceW(dev_info_set, path, 0, &dev_intf_data)) - usb_error::throw_error("internal error (SetupDiOpenDeviceInterfaceW)"); + // create device information set + auto dev_info_set = device_info_set::of_path(path); - auto dev_intf_data_guard = make_scope_exit([dev_info_set, &dev_intf_data]() { - SetupDiDeleteDeviceInterfaceData(dev_info_set, &dev_intf_data); + std::map hub_handles{}; + auto hub_handle_guard = make_scope_exit([&hub_handles]() { + for (auto& hub : hub_handles) + CloseHandle(hub.second); }); - // load device info data - SP_DEVINFO_DATA dev_info_data = { sizeof(dev_info_data) }; - if (!SetupDiGetDeviceInterfaceDetailW(dev_info_set, &dev_intf_data, nullptr, 0, nullptr, &dev_info_data)) { - DWORD err = GetLastError(); - if (err != ERROR_INSUFFICIENT_BUFFER) - throw usb_error("internal error (SetupDiGetDeviceInterfaceDetailW)", err); - } - // create new device - device = create_device(dev_info_set, &dev_info_data); + device = create_device_from_device_info(dev_info_set, path, hub_handles); devices.push_back(device); } catch (const std::exception& e) { @@ -436,3 +371,67 @@ usb_io_callback* usb_registry::get_completion_handler(OVERLAPPED* overlapped) { return it->second; } + +std::vector usb_registry::get_descriptor(HANDLE hub_handle, ULONG usb_port_num, uint16_t descriptor_type, int index, int language_id, int request_size) { + int size = sizeof(USB_DESCRIPTOR_REQUEST) + (request_size != 0 ? request_size : 255); + uint8_t* descriptor_request_buffer = new uint8_t[size]; + auto dev_info_set_guard = make_scope_exit([descriptor_request_buffer]() { + delete[] descriptor_request_buffer; + }); + + // setup request data structure + USB_DESCRIPTOR_REQUEST* descriptor_request = reinterpret_cast(descriptor_request_buffer); + descriptor_request->ConnectionIndex = usb_port_num; + descriptor_request->SetupPacket.bmRequest = 0x80; // device-to-host / type standard / recipient device + descriptor_request->SetupPacket.bRequest = 0x06; // GET_DESCRIPTOR + descriptor_request->SetupPacket.wValue = (descriptor_type << 8) | index; + descriptor_request->SetupPacket.wIndex = language_id; + descriptor_request->SetupPacket.wLength = static_cast(size - sizeof(USB_DESCRIPTOR_REQUEST)); + + // get descriptor + DWORD bytesReturned = 0; + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, descriptor_request, size, descriptor_request, size, &bytesReturned, nullptr)) + throw usb_error("Cannot retrieve descriptor (DeviceIoControl)", GetLastError()); + int data_size = bytesReturned - sizeof(USB_DESCRIPTOR_REQUEST); + + if (data_size <= 2) + throw usb_error("invalid descriptor"); + + // determine expected size of descriptor + int expected_size; + if (descriptor_type != USB_CONFIGURATION_DESCRIPTOR_TYPE) { + expected_size = descriptor_request->Data[0]; + } + else { + auto config_desc = reinterpret_cast(descriptor_request->Data); + expected_size = config_desc->wTotalLength; + } + + // check against effective size + if (data_size < expected_size) { + if (request_size != 0) + throw usb_error("Unexpected descriptor size"); + + // repeat with larger size + return get_descriptor(hub_handle, usb_port_num, descriptor_type, index, language_id, expected_size); + } + + return std::vector(descriptor_request->Data, descriptor_request->Data + data_size); +} + +std::string usb_registry::get_string(HANDLE hub_handle, ULONG usb_port_num, int index) { + if (index == 0) + return ""; + + std::vector str_desc_raw = get_descriptor(hub_handle, usb_port_num, USB_STRING_DESCRIPTOR_TYPE, index, 0x0409); + USB_STRING_DESCRIPTOR* str_desc = reinterpret_cast(str_desc_raw.data()); + + // required length of UTF-8 string + int len = WideCharToMultiByte(CP_UTF8, 0, str_desc->bString, str_desc->bLength / 2 - 1, nullptr, 0, nullptr, nullptr); + + // convert to UTF-8 + std::string result; + result.resize(len, 'x'); + WideCharToMultiByte(CP_UTF8, 0, str_desc->bString, str_desc->bLength / 2 - 1, &result[0], len, nullptr, nullptr); + return result; +} diff --git a/reference/windows/USB/usb_registry.hpp b/reference/windows/USB/usb_registry.hpp index fe66b060..321bf18c 100644 --- a/reference/windows/USB/usb_registry.hpp +++ b/reference/windows/USB/usb_registry.hpp @@ -25,6 +25,8 @@ #undef LowSpeed #include +class device_info_set; + /** * Registry of connected USB devices. */ @@ -50,14 +52,17 @@ class usb_registry { void monitor(); void detect_present_devices(); - std::map enumerate_child_devices(const std::vector child_ids); - + std::shared_ptr create_device_from_device_info(device_info_set& dev_info_set, std::wstring&& device_path, std::map& hub_handles); + std::shared_ptr create_device(std::wstring&& device_path, bool is_composite, HANDLE hub_handle, DWORD usb_port_num); + + static std::string get_string(HANDLE hub_handle, ULONG usb_port_num, int index); + static std::vector get_descriptor(HANDLE hub_handle, ULONG usb_port_num, uint16_t descriptor_type, int index, int language_id, int request_size = 0); + void on_device_connected(const WCHAR* path); void on_device_disconnected(const WCHAR* path); bool handle_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT handle_windows_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - std::shared_ptr create_device(HDEVINFO dev_info_set, SP_DEVINFO_DATA* dev_info); std::vector devices; diff --git a/test-devices/composite-stm32/README.md b/test-devices/composite-stm32/README.md index eb8e508e..bdea2084 100644 --- a/test-devices/composite-stm32/README.md +++ b/test-devices/composite-stm32/README.md @@ -15,22 +15,14 @@ To upload the firmware, the STM32F4x microcontroller have a built-in USB bootloa ### Endpoints -#define EP_CDC_COMM 0x83 -#define EP_CDC_DATA_RX 0x02 -#define EP_CDC_DATA_TX 0x81 - -#define EP_LOOPBACK_RX 0x01 -#define EP_LOOPBACK_TX 0x82 - - -| Endpoint | Transfer Type | Direction | Packet Size | Function | -| - | - | - | - | - | -| 0x00 | Control | Bidirectional | | See *Control requests* below | -| 0x81 | Bulk | Device to host | 64 bytes | CDC: Serial data from device to host. | -| 0x02 | Bulk | Host to device | 64 bytes | CDC: Serial data from host to device. | -| 0x83 | Interrupt | Device to host | 64 bytes | CDC: Serial state events (not used). | -| 0x01 | Bulk | Host to device | 64 bytes | Loopback: all data received on this endpoint is transmitted on endpoint 0x82. | -| 0x82 | Bulk | Device to host | 64 bytes | Loopback: Transmits the data received on endpoint 0x01. | +| Endpoint | Transfer Type | Direction | Packet Size | Interface | Function | +| - | - | - | - | - | - | +| 0x00 | Control | Bidirectional | | 2 | See *Control requests* below | +| 0x81 | Bulk | Device to host | 64 bytes | 1 | CDC: Serial data from device to host. | +| 0x02 | Bulk | Host to device | 64 bytes | 1 | CDC: Serial data from host to device. | +| 0x83 | Interrupt | Device to host | 64 bytes | 0 | CDC: Serial state events (not used). | +| 0x01 | Bulk | Host to device | 64 bytes | 3 | Loopback: all data received on this endpoint is transmitted on endpoint 0x82. | +| 0x82 | Bulk | Device to host | 64 bytes | 3 | Loopback: Transmits the data received on endpoint 0x01. | The virtual serial port on interfaces 0 and 1 implements the CDC ACM class. All operating systems will recognize it as serial port and will automatically make it available as such. No drivers need to be installed. The implementations connects the incoming and outgoing data in a loopback configuration. So all data sent from the host to the device is send back to the host. Control requests to configure baud rates, parity etc. are accepted but have no effect. And the implementation does not send any state events. @@ -46,6 +38,8 @@ Several vendor-specific control requests are supported for testing: | 0x41 | 0x01 | *value* | 0 | 0 | none | Host to device: *value* is saved in device | | 0x41 | 0x02 | 0 | 0 | 4 | *value* (32-bit LE) | Host to device: *value* is saved in device | | 0xC1 | 0x03 | 0 | 0 | 4 | *value* (32-bit LE) | Device to host: saved *value* is transmitted | +| 0xC1 | 0x05 | 0 | 0 | 1 | *interface number* | Device to host: interface number is transmitted | + ## Building the firmware @@ -81,7 +75,7 @@ To upload using the BlackPill's built-in bootloader: 2. Press the *Boot* button while connecting the board via USB to your computer. By pressing the *Boot* button, the device enters bootloader mode. 3. Verify with `dfu-util --list` that the bootloader is available via USB. If not unplug the device and repeat step 2. 4. Run the below command from the project directory. -5. Unplug and reconnect the board from your computer. The LED should now blink about twice a second. +5. Unplug and reconnect the board from your computer. Both the power and user LED should be lit and the device should appear as a serial device (aka as COM port on Windows). ``` dfu-util --device 0483:df11 --alt 0 --dfuse-address 0x08000000 --reset --download bin/blackpill-fxxx.bin @@ -114,4 +108,4 @@ If you built the firmware yourself, you will find the firmware file in `.pio/bui This code uses the CMSIS 5 library (mainly for startup code and register definitions) and TinyUSB for USB. For easier use with PlatformIO, a copy of TinyUSB is integrated into the project. The used TinyUSB code in `lib/tinyusb` is an unmodified subset of the library. -Since the official TinyUSB vendor class is rather limited, an alternative implementation is provided (see [vendor_custom.h](include/vendor_custom.h) and [vendor_custom.c](src/vendor_custom.c)). \ No newline at end of file +Since the official TinyUSB vendor class is rather limited, an alternative implementation is provided (see [vendor_custom.h](src/vendor_custom.h) and [vendor_custom.c](src/vendor_custom.c)). \ No newline at end of file diff --git a/test-devices/composite-stm32/bin/blackpill-f401cc.bin b/test-devices/composite-stm32/bin/blackpill-f401cc.bin index c2fc3f0f..bba469dc 100755 Binary files a/test-devices/composite-stm32/bin/blackpill-f401cc.bin and b/test-devices/composite-stm32/bin/blackpill-f401cc.bin differ diff --git a/test-devices/composite-stm32/bin/blackpill-f411ce.bin b/test-devices/composite-stm32/bin/blackpill-f411ce.bin index 9b9b6a08..5662aad9 100755 Binary files a/test-devices/composite-stm32/bin/blackpill-f411ce.bin and b/test-devices/composite-stm32/bin/blackpill-f411ce.bin differ diff --git a/test-devices/composite-stm32/bin/bluepill-f103c8.bin b/test-devices/composite-stm32/bin/bluepill-f103c8.bin index fa646529..05dc11a3 100755 Binary files a/test-devices/composite-stm32/bin/bluepill-f103c8.bin and b/test-devices/composite-stm32/bin/bluepill-f103c8.bin differ diff --git a/test-devices/composite-stm32/copy_tinyusb.sh b/test-devices/composite-stm32/copy_tinyusb.sh new file mode 100755 index 00000000..1b1a2f3b --- /dev/null +++ b/test-devices/composite-stm32/copy_tinyusb.sh @@ -0,0 +1,17 @@ +#!/bin/sh +TINYUSB_DIR=../../../tinyusb +rm -rf lib/tinyusb/* +mkdir lib/tinyusb/osal +mkdir lib/tinyusb/class +mkdir lib/tinyusb/portable +mkdir lib/tinyusb/portable/synopsys +mkdir lib/tinyusb/portable/st +cp -R $TINYUSB_DIR/src/class/cdc lib/tinyusb/class +cp -R $TINYUSB_DIR/src/common lib/tinyusb +cp -R $TINYUSB_DIR/src/device lib/tinyusb +cp $TINYUSB_DIR/src/osal/osal.h lib/tinyusb/osal +cp $TINYUSB_DIR/src/osal/osal_none.h lib/tinyusb/osal +cp -R $TINYUSB_DIR/src/portable/synopsys/dwc2 lib/tinyusb/portable/synopsys +cp -R $TINYUSB_DIR/src/portable/st/stm32_fsdev lib/tinyusb/portable/st +cp $TINYUSB_DIR/src/*.c lib/tinyusb +cp $TINYUSB_DIR/src/*.h lib/tinyusb diff --git a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio.h b/test-devices/composite-stm32/lib/tinyusb/class/audio/audio.h deleted file mode 100644 index 70d43128..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio.h +++ /dev/null @@ -1,935 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Audio Audio - * Currently only MIDI subclass is supported - * @{ */ - -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// Audio Device Class Codes - -/// A.2 - Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// A.3 - Audio Function Protocol Codes -typedef enum -{ - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_function_protocol_code_t; - -/// A.5 - Audio Interface Subclass Codes -typedef enum -{ - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming -} audio_subclass_type_t; - -/// A.6 - Audio Interface Protocol Codes -typedef enum -{ - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_interface_protocol_code_t; - -/// A.7 - Audio Function Category Codes -typedef enum -{ - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, -} audio_function_code_t; - -/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_ac_interface_subtype_t; - -/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, -} audio_cs_as_interface_subtype_t; - -/// A.11 - Effect Unit Effect Types -typedef enum -{ - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, -} audio_effect_unit_effect_type_t; - -/// A.12 - Processing Unit Process Types -typedef enum -{ - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, -} audio_processing_unit_process_type_t; - -/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - -/// A.14 - Audio Class-Specific Request Codes -typedef enum -{ - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, -} audio_cs_req_t; - -/// A.17 - Control Selector Codes - -/// A.17.1 - Clock Source Control Selectors -typedef enum -{ - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, -} audio_clock_src_control_selector_t; - -/// A.17.2 - Clock Selector Control Selectors -typedef enum -{ - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, -} audio_clock_sel_control_selector_t; - -/// A.17.3 - Clock Multiplier Control Selectors -typedef enum -{ - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, -} audio_clock_mul_control_selector_t; - -/// A.17.4 - Terminal Control Selectors -typedef enum -{ - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, -} audio_terminal_control_selector_t; - -/// A.17.5 - Mixer Control Selectors -typedef enum -{ - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, -} audio_mixer_control_selector_t; - -/// A.17.6 - Selector Control Selectors -typedef enum -{ - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, -} audio_sel_control_selector_t; - -/// A.17.7 - Feature Unit Control Selectors -typedef enum -{ - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, -} audio_feature_unit_control_selector_t; - -/// A.17.8 Effect Unit Control Selectors - -/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors -typedef enum -{ - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, -} audio_parametric_equalizer_control_selector_t; - -/// A.17.8.2 Reverberation Effect Unit Control Selectors -typedef enum -{ - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, -} audio_reverberation_effect_control_selector_t; - -/// A.17.8.3 Modulation Delay Effect Unit Control Selectors -typedef enum -{ - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, -} audio_modulation_delay_control_selector_t; - -/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors -typedef enum -{ - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, -} audio_dynamic_range_compression_control_selector_t; - -/// A.17.9 Processing Unit Control Selectors - -/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors -typedef enum -{ - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, -} audio_up_down_mix_control_selector_t; - -/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors -typedef enum -{ - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, -} audio_dolby_prologic_control_selector_t; - -/// A.17.9.3 Stereo Extender Processing Unit Control Selectors -typedef enum -{ - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, -} audio_stereo_extender_control_selector_t; - -/// A.17.10 Extension Unit Control Selectors -typedef enum -{ - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, -} audio_extension_unit_control_selector_t; - -/// A.17.11 AudioStreaming Interface Control Selectors -typedef enum -{ - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, -} audio_audiostreaming_interface_control_selector_t; - -/// A.17.12 Encoder Control Selectors -typedef enum -{ - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, -} audio_encoder_control_selector_t; - -/// A.17.13 Decoder Control Selectors - -/// A.17.13.1 MPEG Decoder Control Selectors -typedef enum -{ - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, -} audio_MPEG_decoder_control_selector_t; - -/// A.17.13.2 AC-3 Decoder Control Selectors -typedef enum -{ - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, -} audio_AC3_decoder_control_selector_t; - -/// A.17.13.3 WMA Decoder Control Selectors -typedef enum -{ - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, -} audio_WMA_decoder_control_selector_t; - -/// A.17.13.4 DTS Decoder Control Selectors -typedef enum -{ - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, -} audio_DTS_decoder_control_selector_t; - -/// A.17.14 Endpoint Control Selectors -typedef enum -{ - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, -} audio_EP_control_selector_t; - -/// Terminal Types - -/// 2.1 - Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// 2.2 - Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - -/// 2.3 - Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - -/// Rest is yet to be implemented - -/// Additional Audio Device Class Codes - Source: Audio Data Formats - -/// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, -} audio_data_format_type_I_t; - -/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - -/// Audio Class-Control Values UAC2 -typedef enum -{ - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access -} audio_control_t; - -/// Audio Class-Specific AC Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, -} audio_cs_ac_interface_control_pos_t; - -/// Audio Class-Specific AS Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, -} audio_cs_as_interface_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, -} audio_cs_as_iso_data_ep_attribute_t; - -/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, -} audio_cs_as_iso_data_ep_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, -} audio_cs_as_iso_data_ep_lock_delay_unit_t; - -/// Audio Class-Clock Source Attributes UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, -} audio_clock_source_attribute_t; - -/// Audio Class-Clock Source Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, -} audio_clock_source_control_pos_t; - -/// Audio Class-Clock Selector Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, -} audio_clock_selector_control_pos_t; - -/// Audio Class-Clock Multiplier Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, -} audio_clock_multiplier_control_pos_t; - -/// Audio Class-Input Terminal Controls UAC2 -typedef enum -{ - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, -} audio_terminal_input_control_pos_t; - -/// Audio Class-Output Terminal Controls UAC2 -typedef enum -{ - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, -} audio_terminal_output_control_pos_t; - -/// Audio Class-Feature Unit Controls UAC2 -typedef enum -{ - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, -} audio_feature_unit_control_pos_t; - -/// Audio Class-Audio Channel Configuration UAC2 -typedef enum -{ - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, -} audio_channel_config_t; - -/// AUDIO Channel Cluster Descriptor (4.1) -typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. -} audio_desc_channel_cluster_t; - -/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. -} audio_desc_cs_ac_interface_t; - -/// AUDIO Clock Source Descriptor (4.7.2.1) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. -} audio_desc_clock_source_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. -} audio_desc_clock_selector_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins -#define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ -} - -/// AUDIO Clock Multiplier Descriptor (4.7.2.3) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. -} audio_desc_clock_multiplier_t; - -/// AUDIO Input Terminal Descriptor(4.7.2.4) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first logical channel. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. -} audio_desc_input_terminal_t; - -/// AUDIO Output Terminal Descriptor(4.7.2.5) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. -} audio_desc_output_terminal_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. -} audio_desc_feature_unit_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ -} - -/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. -} audio_desc_cs_as_interface_t; - -/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. -} audio_desc_type_I_format_t; - -/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. -} audio_desc_cs_as_iso_data_ep_t; - -// 5.2.2 Control Request Layout -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - -//// 5.2.3 Control Request Parameter Block Layout - -// 5.2.3.1 1-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_1_t; - -// 5.2.3.2 2-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_2_t; - -// 5.2.3.3 4-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_4_t; - -// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like -// 5.2.3.1 1-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_1_t; - -// 5.2.3.2 2-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_2_t; - -// 5.2.3.3 4-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_4_t; - -// 5.2.3.1 1-byte Control RANGE Parameter Block -#define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ -} - -/// 5.2.3.2 2-byte Control RANGE Parameter Block -#define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -// 5.2.3.3 4-byte Control RANGE Parameter Block -#define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.c b/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.c deleted file mode 100644 index f487fe60..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.c +++ /dev/null @@ -1,2567 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! - * It supports multiple TX and RX channels. - * - * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. - * - * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host - * - * 1. Input data -> SW-FIFO -> MCU USB - * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) - * - * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB - * - * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. - * - * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB - * - * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. - * - * The same holds in the RX case. - * - * */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_AUDIO) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "audio_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Use ring buffer if it's available, some MCUs need extra RAM requirements -#ifndef TUD_AUDIO_PREFER_RING_BUFFER - #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT - #define TUD_AUDIO_PREFER_RING_BUFFER 0 - #else - #define TUD_AUDIO_PREFER_RING_BUFFER 1 - #endif -#endif - -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer -// is available or driver is would need to be changed dramatically - -// Only STM32 and dcd_transdimension use non-linear buffer for now -// dwc2 except esp32sx (since it may use dcd_esp32sx) -#if (defined(TUP_USBIP_DWC2) && !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)) || \ - defined(TUP_USBIP_FSDEV) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N || \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT || \ - CFG_TUSB_MCU == OPT_MCU_MSP432E4 - #if TUD_AUDIO_PREFER_RING_BUFFER - #define USE_LINEAR_BUFFER 0 - #else - #define USE_LINEAR_BUFFER 1 - #endif -#else - #define USE_LINEAR_BUFFER 1 -#endif - -// Temporarily put the check here for stm32_fsdev -#ifdef TUP_USBIP_FSDEV - #define USE_ISO_EP_ALLOCATION 1 -#else - #define USE_ISO_EP_ALLOCATION 0 -#endif - -// Declaration of buffers - -// Check for maximum supported numbers -#if CFG_TUD_AUDIO > 3 -#error Maximum number of audio functions restricted to three! -#endif - -// EP IN software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -// Linear buffer TX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// EP OUT software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -// Linear buffer RX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// Control buffers -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; - -#if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif - -#if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif - -// Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; -#endif - -// Software encoding/decoding support FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif -#endif - -typedef struct -{ - uint8_t rhport; - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in; // TX audio data EP. - uint16_t ep_in_sz; // Current size of TX EP - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint16_t ep_out_sz; // Current size of RX EP - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. -#endif - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. -#endif - - /*------------- From this point, data is not cleared by bus reset -------------*/ - - uint16_t desc_length; // Length of audio function descriptor - - // Buffer for control requests - uint8_t * ctrl_buf; - uint8_t ctrl_buf_sz; - - // Current active alternate settings - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - - // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t ep_out_ff; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - struct { - CFG_TUSB_MEM_ALIGN uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). - uint32_t min_value; // min value according to UAC2 FMT-2.0 section 2.3.1.1. - uint32_t max_value; // max value according to UAC2 FMT-2.0 section 2.3.1.1. - - uint8_t frame_shift; // bInterval-1 in unit of frame (FS), micro-frame (HS) - uint8_t compute_method; - - union { - uint8_t power_of_2; // pre-computed power of 2 shift - float float_const; // pre-computed float constant - - struct { - uint32_t sample_freq; - uint32_t mclk_freq; - }fixed; - -#if 0 // implement later - struct { - uint32_t nominal_value; - uint32_t threshold_bytes; - }fifo_count; -#endif - }compute; - - } feedback; -#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t ep_in_ff; -#endif - - // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; -#endif - - // Decoding parameters - parameters are set when alternate AS interface is set by host - // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - audio_format_type_t format_type_rx; - uint8_t n_channels_rx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sampe_rx; - uint8_t n_channels_per_ff_rx; - uint8_t n_ff_used_rx; -#endif -#endif - - // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - audio_format_type_t format_type_tx; - uint8_t n_channels_tx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio_data_format_type_I_t format_type_I_tx; - uint8_t n_bytes_per_sampe_tx; - uint8_t n_channels_per_ff_tx; - uint8_t n_ff_used_tx; -#endif -#endif - - // Support FIFOs for software encoding and decoding -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t * rx_supp_ff; - uint8_t n_rx_supp_ff; - uint16_t rx_supp_ff_sz_max; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t * tx_supp_ff; - uint8_t n_tx_supp_ff; - uint16_t tx_supp_ff_sz_max; -#endif - - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - uint8_t * lin_buf_out; -#define USE_LINEAR_BUFFER_RX 1 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - uint8_t * lin_buf_in; -#define USE_LINEAR_BUFFER_TX 1 -#endif - -} audiod_function_t; - -#ifndef USE_LINEAR_BUFFER_TX -#define USE_LINEAR_BUFFER_TX 0 -#endif - -#ifndef USE_LINEAR_BUFFER_RX -#define USE_LINEAR_BUFFER_RX 0 -#endif - -#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); -#endif - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); - -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); -static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); - -static inline uint8_t tu_desc_subtype(void const* desc) -{ - return ((uint8_t const*) desc)[2]; -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); -#endif - -bool tud_audio_n_mounted(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in == 0) return false; -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) return false; -#endif - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -uint16_t tud_audio_n_available(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); -} - -uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); -} - -bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -// Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); -} - -tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; - return NULL; -} -#endif - -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - uint8_t idxItf = 0; - uint8_t const *dummy2; - uint8_t idx_audio_fct = 0; - - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) - { - TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - - switch (audio->format_type_rx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_rx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - - // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - -#else - -#if USE_LINEAR_BUFFER_RX - // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); - - // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) - { - TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT - -// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Decoding according to 2.3.1.5 Audio Streams - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) -{ - - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint8_t *)dst++ = *src; - src += n_ff_used; - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - dst += 4; - src += 4 * n_ff_used; - } - break; - } - - return src; -} - -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - (void) rhport; - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; - uint8_t cnt_ff; - - // Decode - uint8_t * src; - uint8_t * dst_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); - if (info.len_wrap != 0) - { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); - } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it - // TU_VERIFY(cnt != n_bytes); - - return true; -} -#endif //CFG_TUD_AUDIO_ENABLE_DECODING - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] func_id: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); -} - -bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[func_id]; - - uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); - - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - - n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); - n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; - - return n_bytes_copied; -} - -bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); -} - -tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; - return NULL; -} - -#endif - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); - - TU_VERIFY(tu_memcpy_s(_audiod_fct[func_id].ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE, buffer, len)==0); - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); - - return true; -} - -#endif - - -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. - -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) -{ - uint8_t idxItf; - uint8_t const *dummy2; - - uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); - - // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications - if (audio->alt_setting[idxItf] == 0) return false; - - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx; - - // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - switch (audio->format_type_tx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - - n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); - break; - - default: - // YOUR ENCODING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - -#else - // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - -#if USE_LINEAR_BUFFER_TX - tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); -#else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -// Take samples from the support buffer and encode them into the IN EP software FIFO -// Returns number of bytes written into linear buffer - -/* 2.3.1.7.1 PCM Format -The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio -data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It -is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused -bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the -range [-1, +1) - */ - -/* - * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples - * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and - * does not change the number of bytes per sample. - * */ - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) -{ - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while(src < src_end) - { - *dst = *src++; - dst += n_ff_used; - } - break; - - case 2: - while(src < src_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; - } - break; - - case 3: - while(src < src_end) - { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - src += 4; - dst += 4 * n_ff_used; - } - break; - } - - return dst; -} - -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) -{ - // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap - // This is ensured within set_interface, where the FIFOs are reconfigured according to this size - - // We encode directly into IN EP's linear buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; - uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes - uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); - uint8_t cnt_ff; - - for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) - { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nBytesPerFFToSend) - { - nBytesPerFFToSend = count; - } - } - - // Check if there is enough - if (nBytesPerFFToSend == 0) return 0; - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); - - // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; - - // Encode - uint8_t * dst; - uint8_t * src_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); - - // Limit up to desired length - info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) - { - src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); - } - - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - return nBytesPerFFToSend * n_ff_used; -} -#endif //CFG_TUD_AUDIO_ENABLE_ENCODING - -// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) -{ - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->feedback.value, 4); -} -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void audiod_init(void) -{ - tu_memclr(_audiod_fct, sizeof(_audiod_fct)); - - for(uint8_t i=0; ictrl_buf = ctrl_buf_1; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; - break; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 - case 1: - audio->ctrl_buf = ctrl_buf_2; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 - case 2: - audio->ctrl_buf = ctrl_buf_3; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; - break; -#endif - } - - // Initialize active alternate interface buffers - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 - case 0: - audio->alt_setting = alt_setting_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 - case 1: - audio->alt_setting = alt_setting_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - case 2: - audio->alt_setting = alt_setting_3; - break; -#endif - } - - // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_TX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - case 0: - audio->lin_buf_in = lin_buf_in_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - case 1: - audio->lin_buf_in = lin_buf_in_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - case 2: - audio->lin_buf_in = lin_buf_in_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_RX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - case 0: - audio->lin_buf_out = lin_buf_out_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - case 1: - audio->lin_buf_out = lin_buf_out_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - case 2: - audio->lin_buf_out = lin_buf_out_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->tx_supp_ff = tx_supp_ff_1; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->tx_supp_ff = tx_supp_ff_2; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->tx_supp_ff = tx_supp_ff_3; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - - // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->rx_supp_ff = rx_supp_ff_1; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->rx_supp_ff = rx_supp_ff_2; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->rx_supp_ff = rx_supp_ff_3; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - } -} - -void audiod_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; iep_in_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - } -} - -uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_fct[i].p_desc) - { - _audiod_fct[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - _audiod_fct[i].rhport = rhport; - - // Setup descriptor lengths - switch (i) - { - case 0: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; - break; -#if CFG_TUD_AUDIO > 1 - case 1: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; - break; -#endif -#if CFG_TUD_AUDIO > 2 - case 2: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; - break; -#endif - } - -#if USE_ISO_EP_ALLOCATION - #if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in = 0; - uint16_t ep_in_size = 0; - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out = 0; - uint16_t ep_out_size = 0; - #endif - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb = 0; - #endif - - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Explicit feedback EP - if (desc_ep->bmAttributes.usage == 1) - { - ep_fb = desc_ep->bEndpointAddress; - } - #endif - // Data EP - if (desc_ep->bmAttributes.usage == 0) - { - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - #if CFG_TUD_AUDIO_ENABLE_EP_IN - ep_in = desc_ep->bEndpointAddress; - ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); - #endif - } else - { - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - ep_out = desc_ep->bEndpointAddress; - ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); - #endif - } - } - - } - } - p_desc = tu_desc_next(p_desc); - } - - #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (ep_in) - { - usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (ep_out) - { - usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (ep_fb) - { - usbd_edpt_iso_alloc(rhport, ep_fb, 4); - } - #endif - -#endif // USE_ISO_EP_ALLOCATION - - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; -} - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - uint8_t const itf = tu_u16_low(p_request->wIndex); - - // Find index of audio streaming interface - uint8_t func_id, idxItf; - uint8_t const *dummy; - - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); - - return true; -} - -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Here we need to do the following: - - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - - // 3. Open new EP - - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); - - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - - // Find index of audio streaming interface and index of interface - uint8_t func_id, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - - audiod_function_t* audio = &_audiod_fct[func_id]; - - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in_as_intf_num == itf) - { - audio->ep_in_as_intf_num = 0; - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_in); - #endif - - // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_clear(&audio->ep_in_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } - #endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_in = 0; // Necessary? - - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out_as_intf_num == itf) - { - audio->ep_out_as_intf_num = 0; - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_out); - #endif - - // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } - #endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_out = 0; // Necessary? - - // Close corresponding feedback EP - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_fb); - #endif - audio->ep_fb = 0; - tu_memclr(&audio->feedback, sizeof(audio->feedback)); - #endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - // Save current alternative interface setting - audio->alt_setting[idxItf] = alt; - - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) - { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING - uint8_t const * p_desc_parse_for_params = p_desc; -#endif - // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary - uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; - while (foundEPs < nEps && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; -#if USE_ISO_EP_ALLOCATION - TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep)); -#else - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); -#endif - uint8_t const ep_addr = desc_ep->bEndpointAddress; - - //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! - usbd_edpt_clear_stall(rhport, ep_addr); - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - audio->ep_in = ep_addr; - audio->ep_in_as_intf_num = itf; - audio->ep_in_sz = tu_edpt_packet_size(desc_ep); - - // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters - #if CFG_TUD_AUDIO_ENABLE_ENCODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx); - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; - TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); - #endif - #endif - - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - audio->ep_out = ep_addr; - audio->ep_out_as_intf_num = itf; - audio->ep_out_sz = tu_edpt_packet_size(desc_ep); - - #if CFG_TUD_AUDIO_ENABLE_DECODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; - TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); - #endif - #endif - - // Prepare for incoming data - #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - #else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); - #endif - } - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback - { - audio->ep_fb = ep_addr; - audio->feedback.frame_shift = desc_ep->bInterval -1; - - // Enable SOF interrupt if callback is implemented - if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, true); - } - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } - - TU_VERIFY(foundEPs == nEps); - - // Invoke one callback for a final set interface - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Prepare feedback computation if callback is available - if (tud_audio_feedback_params_cb) - { - audio_feedback_params_t fb_param; - - tud_audio_feedback_params_cb(func_id, alt, &fb_param); - audio->feedback.compute_method = fb_param.method; - - // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) - uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; - audio->feedback.min_value = (fb_param.sample_freq/frame_div - 1) << 16; - audio->feedback.max_value = (fb_param.sample_freq/frame_div + 1) << 16; - - switch(fb_param.method) - { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); - break; - - #if 0 // implement later - case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: - { - uint64_t fb64 = ((uint64_t) fb_param.sample_freq) << 16; - audio->feedback.compute.fifo_count.nominal_value = (uint32_t) (fb64 / frame_div); - audio->feedback.compute.fifo_count.threshold_bytes = fb_param.fifo_count.threshold_bytes; - - tud_audio_fb_set(audio->feedback.compute.fifo_count.nominal_value); - } - break; - #endif - - // nothing to do - default: break; - } - } -#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - - // We are done - abort loop - break; - } - - // Moving forward - p_desc = tu_desc_next(p_desc); - } - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Disable SOF interrupt if no driver has any enabled feedback EP - bool disable = true; - for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].ep_fb != 0) - { - disable = false; - break; - } - } - if (disable) usbd_sof_enable(rhport, false); -#endif - - tud_control_status(rhport, p_request); - - return true; -} - -// Invoked when class request DATA stage is finished. -// return false to stall control EP (e.g Host send non-sense DATA) -static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) - { - uint8_t func_id; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - break; - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } - } - return true; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); - - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t func_id; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); - return true; - } - - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; -} - -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - return audiod_control_request(rhport, request); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - return audiod_control_complete(rhport, request); - } - - return true; -} - -bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) xferred_bytes; - - // Search for interface belonging to given end point address and proceed as required - for (uint8_t func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) - { - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - - // Data transmission of control interrupt finished - if (audio->ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // I assume here, that things above are handled by PHY - // All transmission is done - what remains to do is to inform job was completed - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); - } - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - - // Data transmission of audio packet finished - if (audio->ep_in == ep_addr && audio->alt_setting != 0) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, audio)); - - // Transmission of ZLP is done by audiod_tx_done_cb() - return true; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - // New audio packet received - if (audio->ep_out == ep_addr) - { - TU_VERIFY(audiod_rx_done_cb(rhport, audio, (uint16_t) xferred_bytes)); - return true; - } - - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (audio->ep_fb == ep_addr) - { - if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id); - - // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, audio->ep_fb)) - { - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, audio); - } - } -#endif -#endif - } - - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) -{ - // Check if frame interval is within sane limits - // The interval value n_frames was taken from the descriptors within audiod_set_interface() - - // n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 * f_s / f_m) for high speed - // this lower limit ensures the measures feedback value has sufficient precision - uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13; - uint32_t const n_frame = (1UL << audio->feedback.frame_shift); - - if ( (((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame ) - { - TU_LOG1(" UAC2 feedback interval too small\r\n"); TU_BREAKPOINT(); return false; - } - - // Check if parameters really allow for a power of two division - if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq)) - { - audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; - audio->feedback.compute.power_of_2 = 16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq); - } - else if ( audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) - { - audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - audio->feedback.frame_shift)); - } - else - { - audio->feedback.compute.fixed.sample_freq = sample_freq; - audio->feedback.compute.fixed.mclk_freq = mclk_freq; - } - - return true; -} - -uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) -{ - audiod_function_t* audio = &_audiod_fct[func_id]; - uint32_t feedback; - - switch (audio->feedback.compute_method) - { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - feedback = (cycles << audio->feedback.compute.power_of_2); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - feedback = (uint32_t) ((float) cycles * audio->feedback.compute.float_const); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: - { - uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - audio->feedback.frame_shift); - feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); - } - break; - - default: return 0; - } - - // For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers - // The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. - // This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot - // (audio slot = channel count samples). - if ( feedback > audio->feedback.max_value ) feedback = audio->feedback.max_value; - if ( feedback < audio->feedback.min_value ) feedback = audio->feedback.min_value; - - tud_audio_n_fb_set(func_id, feedback); - - return feedback; -} -#endif - -TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) -{ - (void) rhport; - (void) frame_count; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec - // Boiled down, the feedback value Ff = n_samples / (micro)frame. - // Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) - // The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) - // feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - - // Iterate over audio functions and set feedback value - for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) - { - audiod_function_t* audio = &_audiod_fct[i]; - - if (audio->ep_fb != 0) - { - // HS shift need to be adjusted since SOF event is generated for frame only - uint8_t const hs_adjust = (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0; - uint32_t const interval = 1UL << (audio->feedback.frame_shift - hs_adjust); - if ( 0 == (frame_count & (interval-1)) ) - { - if(tud_audio_feedback_interval_isr) tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); - } - } - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -} - -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) -{ - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - - // Get corresponding driver index - uint8_t func_id; - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // Crop length - if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; - - // Copy into buffer - TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len)); - - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); -} - -// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - if (audio->p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(audio->p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) - { - if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; - } - // Increase index, bytes read, and pointer - tmp++; - } - p_desc = tu_desc_next(p_desc); - } - } - return false; -} - -// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) - { - *func_id = i; - return true; - } - } - - return false; -} - -// Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -// p_desc points to the AS interface of alternate setting zero -// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter -// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) -{ -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) return; // Abort, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) return; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) return; -#endif - - p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor - - while (p_desc < p_desc_end) - { - // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; - - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); -#endif - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; -#endif - } -#endif - } - - // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - } -#endif - - // Other format types are not supported yet - - p_desc = tu_desc_next(p_desc); - } -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].feedback.value; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].feedback.value = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - -// No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) -{ - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) - { - if (&_audiod_fct[cnt] == audio) return cnt; - } - return 0; -} - -#endif //CFG_TUD_ENABLED && CFG_TUD_AUDIO diff --git a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.h b/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.h deleted file mode 100644 index 7c88b99f..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/audio/audio_device.h +++ /dev/null @@ -1,699 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_AUDIO_DEVICE_H_ -#define _TUSB_AUDIO_DEVICE_H_ - -#include "audio.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// All sizes are in bytes! - -#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif - -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces -#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif - -// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif - -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN -#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT -#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX -#endif - -// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Software EP FIFO buffer sizes - must be >= max EP SIZEs! -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 -#endif - -// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 -#endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -// Use software encoding/decoding - -// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved -// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. -// -// Currently, only PCM type I encoding/decoding is supported! -// -// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. - -// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the -// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using -// - tud_audio_n_write() or -// - tud_audio_n_read(). -// To write/read to/from the support FIFOs use -// - tud_audio_n_write_support_ff() or -// - tud_audio_n_read_support_ff(). -// -// The encoding/decoding format type done is defined below. -// -// The encoding/decoding starts when the private callback functions -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. -// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// if you want to get informed what happened. -// -// If you don't use the support FIFOs you may use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. -// -// If you need a different encoding which is not support so far implement it in the -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// functions. - -// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual coding parameters of active AS alternate interface is parsed from the descriptors - -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! -// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! - -// For PCM encoding/decoding - -#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_DECODING -#define CFG_TUD_AUDIO_ENABLE_DECODING 0 -#endif - -// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 -#endif - -// Type I Coding parameters not given within UAC2 descriptors -// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -// Remaining types not support so far - -// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface -#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 -#endif - -// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO -#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 -#endif - -//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); - -// Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup AUDIO_Serial Serial - * @{ - * \defgroup AUDIO_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_AUDIO > 1 -//--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t func_id); - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t func_id); -uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO -tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); -tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO -tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); -tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); -#endif - -//--------------------------------------------------------------------+ -// Application API (Interface0) -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted (void); - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void); -static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline bool tud_audio_clear_ep_in_ff (void); -static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); -static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); -#endif - -// INT CTR API - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); -#endif - -// Buffer control EP data and schedule a transmit -// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a -// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. -// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such -// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id); - - -// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced. - -// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). - -// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set(). - -// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. -// -// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. -// -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. - -// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value. - -// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec -// Boiled down, the feedback value Ff = n_samples / (micro)frame. -// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) -// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) -// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); - -// Update feedback value with passed cycles since last time this update function is called. -// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented -// This function will also call tud_audio_feedback_set() -// return feedback value in 16.16 for reference (0 for error) -uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles); - -enum { - AUDIO_FEEDBACK_METHOD_DISABLED, - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED, - AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT, - AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, - - // impelemnt later - // AUDIO_FEEDBACK_METHOD_FIFO_COUNT -}; - -typedef struct { - uint8_t method; - uint32_t sample_freq; // sample frequency in Hz - - union { - struct { - uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on - }frequency; - -#if 0 // implement later - struct { - uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready - }fifo_count; -#endif - }; -}audio_feedback_params_t; - -// Invoked when needed to set feedback parameters -TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); - -// Callback in ISR context, invoked periodically according to feedback endpoint bInterval. -// Could be used to compute and update feedback value, should be placed in RAM if possible -// frame_number : current SOF count -// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor -TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); -#endif - -// Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted(void) -{ - return tud_audio_n_mounted(0); -} - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -static inline uint16_t tud_audio_available(void) -{ - return tud_audio_n_available(0); -} - -static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read(0, buffer, bufsize); -} - -static inline bool tud_audio_clear_ep_out_ff(void) -{ - return tud_audio_n_clear_ep_out_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) -{ - return tud_audio_n_get_ep_out_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - -static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_rx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_available_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); -} - -static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_rx_support_ff(0, ff_idx); -} - -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_write(const void * data, uint16_t len) -{ - return tud_audio_n_write(0, data, len); -} - -static inline bool tud_audio_clear_ep_in_ff(void) -{ - return tud_audio_n_clear_ep_in_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) -{ - return tud_audio_n_get_ep_in_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_flush_tx_support_ff(void) -{ - return tud_audio_n_flush_tx_support_ff(0); -} - -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_tx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) -{ - return tud_audio_n_write_support_ff(0, ff_idx, data, len); -} - -static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_tx_support_ff(0, ff_idx); -} - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) -{ - return tud_audio_int_ctr_n_write(0, buffer, len); -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -static inline bool tud_audio_fb_set(uint32_t feedback) -{ - return tud_audio_n_fb_set(0, feedback); -} - -#endif - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); -void audiod_sof_isr (uint8_t rhport, uint32_t frame_count); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_AUDIO_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.c b/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.c deleted file mode 100755 index f96bb355..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_BTH) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "bth_device.h" -#include - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_ev; - uint8_t ep_acl_in; - uint8_t ep_acl_out; - uint8_t ep_voice[2]; // Not used yet - uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; - -} btd_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; - -static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) -{ - uint8_t const rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, ep)); - - TU_ASSERT(usbd_edpt_xfer(rhport, ep, data, len)); - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -bool tud_bt_event_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_ev, event, event_len); -} - -bool tud_bt_acl_data_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void btd_init(void) -{ - tu_memclr(&_btd_itf, sizeof(_btd_itf)); -} - -void btd_reset(uint8_t rhport) -{ - (void)rhport; -} - -uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - tusb_desc_endpoint_t const *desc_ep; - uint16_t drv_len = 0; - // Size of single alternative of ISO interface - const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); - // Size of hci interface - const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); - // Ensure this is BT Primary Controller - TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - - TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); - - _btd_itf.itf_num = itf_desc->bInterfaceNumber; - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - _btd_itf.ep_ev = desc_ep->bEndpointAddress; - - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, - &_btd_itf.ep_acl_in), 0); - - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); - - // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); - - drv_len = hci_itf_size; - - // Ensure this is still BT Primary Controller - TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); - - uint8_t dir; - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - - for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { - // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); - if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || - TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || - TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { - // Not an Iso interface instance - break; - } - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ - (void)rhport; - - if ( stage == CONTROL_STAGE_SETUP ) - { - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) - { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) - { - // TODO: Set interface it would involve changing size of endpoint size - } - else - { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); - } - } - else return false; - - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); - } - - return true; -} - -bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - - // received new data from host - if (ep_addr == _btd_itf.ep_acl_out) - { - if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); - - // prepare for next data - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); - } - else if (ep_addr == _btd_itf.ep_ev) - { - if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); - } - else if (ep_addr == _btd_itf.ep_acl_in) - { - if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); - } - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.h b/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.h deleted file mode 100755 index 921bd7a1..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/bth/bth_device.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ - -#include -#include - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#ifndef CFG_TUD_BTH_EVENT_EPSIZE -#define CFG_TUD_BTH_EVENT_EPSIZE 16 -#endif -#ifndef CFG_TUD_BTH_DATA_EPSIZE -#define CFG_TUD_BTH_DATA_EPSIZE 64 -#endif - -typedef struct TU_ATTR_PACKED -{ - uint16_t op_code; - uint8_t param_length; - uint8_t param[255]; -} bt_hci_cmd_t; - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when HCI command was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.1. -// Length of the command is from 3 bytes (2 bytes for OpCode, -// 1 byte for parameter total length) to 258. -TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); - -// Invoked when ACL data was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.2. -// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length) to endpoint size. -TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); - -// Called when event sent with tud_bt_event_send() was delivered to BT stack. -// Controller can release/reuse buffer with Event packet at this point. -TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); - -// Called when ACL data that was sent with tud_bt_acl_data_send() -// was delivered to BT stack. -// Controller can release/reuse buffer with ACL packet at this point. -TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); - -// Bluetooth controller calls this function when it wants to send even packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. -// Event has at least 2 bytes, first is Event code second contains parameter -// total length. Controller can release/reuse event memory after -// tud_bt_event_sent_cb() is called. -bool tud_bt_event_send(void *event, uint16_t event_len); - -// Bluetooth controller calls this to send ACL data packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 -// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length). Upper limit is not limited -// to endpoint size since buffer is allocate by controller -// and must not be reused till tud_bt_acl_data_sent_cb() is called. -bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc.h index 4658e43a..5cbd658f 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc.h +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc.h @@ -136,8 +136,7 @@ typedef enum{ //--------------------------------------------------------------------+ /// Communication Interface Management Element Request Codes -typedef enum -{ +typedef enum { CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. CDC_REQUEST_SET_COMM_FEATURE = 0x02, @@ -180,37 +179,38 @@ typedef enum CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, -}cdc_management_request_t; +} cdc_management_request_t; -enum -{ +typedef enum { CDC_CONTROL_LINE_STATE_DTR = 0x01, CDC_CONTROL_LINE_STATE_RTS = 0x02, -}; +} cdc_control_line_state_t; -enum -{ - CDC_LINE_CONDING_STOP_BITS_1 = 0, // 1 bit - CDC_LINE_CONDING_STOP_BITS_1_5 = 1, // 1.5 bits - CDC_LINE_CONDING_STOP_BITS_2 = 2, // 2 bits -}; +typedef enum { + CDC_LINE_CODING_STOP_BITS_1 = 0, // 1 bit + CDC_LINE_CODING_STOP_BITS_1_5 = 1, // 1.5 bits + CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits +} cdc_line_coding_stopbits_t; -enum -{ +// TODO Backward compatible for typos. Maybe removed in the future release +#define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 +#define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5 +#define CDC_LINE_CONDING_STOP_BITS_2 CDC_LINE_CODING_STOP_BITS_2 + +typedef enum { CDC_LINE_CODING_PARITY_NONE = 0, CDC_LINE_CODING_PARITY_ODD = 1, CDC_LINE_CODING_PARITY_EVEN = 2, CDC_LINE_CODING_PARITY_MARK = 3, CDC_LINE_CODING_PARITY_SPACE = 4, -}; +} cdc_line_coding_parity_t; //--------------------------------------------------------------------+ // Management Element Notification (Notification Endpoint) //--------------------------------------------------------------------+ /// 6.3 Notification Codes -typedef enum -{ +typedef enum { CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.c b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.c index 5adce521..2e0a0c30 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.c +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.c @@ -33,13 +33,17 @@ #include "cdc_device.h" +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUD_CDC_LOG_LEVEL + #define CFG_TUD_CDC_LOG_LEVEL CFG_TUD_LOG_LEVEL +#endif + +#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_CDC_LOG_LEVEL, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -enum -{ - BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) -}; +#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) typedef struct { @@ -76,7 +80,7 @@ typedef struct //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; +CFG_TUD_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { @@ -143,7 +147,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) bufsize); + uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); _prep_out_transaction(p_cdc); return num_read; } @@ -166,12 +170,14 @@ void tud_cdc_n_read_flush (uint8_t itf) uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) bufsize); + uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); // flush if queue more than packet size - // may need to suppress -Wunreachable-code since most of the time CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - if ( (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE) || ((CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE) && tu_fifo_full(&p_cdc->tx_ff)) ) - { + if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE + #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE + || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size + #endif + ) { tud_cdc_n_write_flush(itf); } @@ -246,9 +252,37 @@ void cdcd_init(void) // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); + #if OSAL_MUTEX_REQUIRED + osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex); + osal_mutex_t mutex_wr = osal_mutex_create(&p_cdc->tx_ff_mutex); + TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, ); + + tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, mutex_rd); + tu_fifo_config_mutex(&p_cdc->tx_ff, mutex_wr, NULL); + #endif + } +} + +bool cdcd_deinit(void) { + #if OSAL_MUTEX_REQUIRED + for(uint8_t i=0; irx_ff.mutex_rd; + osal_mutex_t mutex_wr = p_cdc->tx_ff.mutex_wr; + + if (mutex_rd) { + osal_mutex_delete(mutex_rd); + tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, NULL); + } + + if (mutex_wr) { + osal_mutex_delete(mutex_wr); + tu_fifo_config_mutex(&p_cdc->tx_ff, NULL, NULL); + } } + #endif + + return true; } void cdcd_reset(uint8_t rhport) @@ -353,7 +387,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t case CDC_REQUEST_SET_LINE_CODING: if (stage == CONTROL_STAGE_SETUP) { - TU_LOG2(" Set Line Coding\r\n"); + TU_LOG_DRV(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } else if ( stage == CONTROL_STAGE_ACK) @@ -365,7 +399,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t case CDC_REQUEST_GET_LINE_CODING: if (stage == CONTROL_STAGE_SETUP) { - TU_LOG2(" Get Line Coding\r\n"); + TU_LOG_DRV(" Get Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } break; @@ -390,7 +424,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t // Disable fifo overwriting if DTR bit is set tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); + TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); @@ -403,7 +437,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if (stage == CONTROL_STAGE_ACK) { - TU_LOG2(" Send Break\r\n"); + TU_LOG_DRV(" Send Break\r\n"); if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); } break; diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.h index a6e07aa5..20e90845 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.h +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_device.h @@ -247,6 +247,7 @@ static inline bool tud_cdc_write_clear(void) // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void cdcd_init (void); +bool cdcd_deinit (void); void cdcd_reset (uint8_t rhport); uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.c b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.c index fe3691bf..133a10f6 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.c +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.c @@ -22,6 +22,9 @@ * THE SOFTWARE. * * This file is part of the TinyUSB stack. + * + * Contribution + * - Heiko Kuester: CH34x support */ #include "tusb_option.h" @@ -29,14 +32,16 @@ #if (CFG_TUH_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "cdc_host.h" -// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message -#define CDCH_DEBUG 2 +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUH_CDC_LOG_LEVEL + #define CFG_TUH_CDC_LOG_LEVEL CFG_TUH_LOG_LEVEL +#endif -#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -48,12 +53,18 @@ typedef struct { uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; + uint8_t ep_notif; uint8_t serial_drid; // Serial Driver ID + bool mounted; // Enumeration is complete cdc_acm_capability_t acm_capability; - uint8_t ep_notif; - uint8_t line_state; // DTR (bit0), RTS (bit1) TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width + uint8_t line_state; // DTR (bit0), RTS (bit1) + + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X + cdc_line_coding_t requested_line_coding; + // 1 byte padding + #endif tuh_xfer_cb_t user_control_cb; @@ -67,7 +78,6 @@ typedef struct { uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; } stream; - } cdch_interface_t; CFG_TUH_MEM_SECTION @@ -78,47 +88,60 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; //--------------------------------------------------------------------+ //------------- ACM prototypes -------------// +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void acm_process_config(tuh_xfer_t* xfer); +static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI #include "serial/ftdi_sio.h" -static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST }; -enum { - FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0]) -}; - -// Store last request baudrate since divisor to baudrate is not easy -static uint32_t _ftdi_requested_baud; +static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); static void ftdi_process_config(tuh_xfer_t* xfer); -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CP210X prototypes -------------// #if CFG_TUH_CDC_CP210X #include "serial/cp210x.h" -static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST }; -enum { - CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0]) -}; +static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void cp210x_process_config(tuh_xfer_t* xfer); -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +#endif + +//------------- CH34x prototypes -------------// +#if CFG_TUH_CDC_CH34X +#include "serial/ch34x.h" + +static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; + +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len); +static void ch34x_process_config(tuh_xfer_t* xfer); + +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif +//------------- Common -------------// enum { SERIAL_DRIVER_ACM = 0, @@ -129,60 +152,96 @@ enum { #if CFG_TUH_CDC_CP210X SERIAL_DRIVER_CP210X, #endif + +#if CFG_TUH_CDC_CH34X + SERIAL_DRIVER_CH34X, +#endif + + SERIAL_DRIVER_COUNT }; typedef struct { + uint16_t const (*vid_pid_list)[2]; + uint16_t const vid_pid_count; + bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); void (*const process_set_config)(tuh_xfer_t* xfer); bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); } cdch_serial_driver_t; // Note driver list must be in the same order as SERIAL_DRIVER enum static const cdch_serial_driver_t serial_drivers[] = { - { .process_set_config = acm_process_config, - .set_control_line_state = acm_set_control_line_state, - .set_baudrate = acm_set_baudrate + { + .vid_pid_list = NULL, + .vid_pid_count = 0, + .open = acm_open, + .process_set_config = acm_process_config, + .set_control_line_state = acm_set_control_line_state, + .set_baudrate = acm_set_baudrate, + .set_data_format = acm_set_data_format, + .set_line_coding = acm_set_line_coding }, #if CFG_TUH_CDC_FTDI - { .process_set_config = ftdi_process_config, - .set_control_line_state = ftdi_sio_set_modem_ctrl, - .set_baudrate = ftdi_sio_set_baudrate + { + .vid_pid_list = ftdi_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), + .open = ftdi_open, + .process_set_config = ftdi_process_config, + .set_control_line_state = ftdi_sio_set_modem_ctrl, + .set_baudrate = ftdi_sio_set_baudrate, + .set_data_format = ftdi_set_data_format, + .set_line_coding = ftdi_set_line_coding }, #endif #if CFG_TUH_CDC_CP210X - { .process_set_config = cp210x_process_config, - .set_control_line_state = cp210x_set_modem_ctrl, - .set_baudrate = cp210x_set_baudrate + { + .vid_pid_list = cp210x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), + .open = cp210x_open, + .process_set_config = cp210x_process_config, + .set_control_line_state = cp210x_set_modem_ctrl, + .set_baudrate = cp210x_set_baudrate, + .set_data_format = cp210x_set_data_format, + .set_line_coding = cp210x_set_line_coding }, #endif -}; -enum { - SERIAL_DRIVER_COUNT = sizeof(serial_drivers) / sizeof(serial_drivers[0]) + #if CFG_TUH_CDC_CH34X + { + .vid_pid_list = ch34x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), + .open = ch34x_open, + .process_set_config = ch34x_process_config, + .set_control_line_state = ch34x_set_modem_ctrl, + .set_baudrate = ch34x_set_baudrate, + .set_data_format = ch34x_set_data_format, + .set_line_coding = ch34x_set_line_coding + }, + #endif }; +TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial driver count mismatch"); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static inline cdch_interface_t* get_itf(uint8_t idx) -{ +static inline cdch_interface_t* get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); cdch_interface_t* p_cdc = &cdch_data[idx]; return (p_cdc->daddr != 0) ? p_cdc : NULL; } -static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) -{ - for(uint8_t i=0; idaddr == daddr) && - (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) - { + (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) { return i; } } @@ -190,14 +249,10 @@ static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) return TUSB_INDEX_INVALID_8; } - -static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc) -{ - for(uint8_t i=0; idaddr = daddr; p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; @@ -218,20 +273,16 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer); // APPLICATION API //--------------------------------------------------------------------+ -uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for(uint8_t i=0; idaddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i; } return TUSB_INDEX_INVALID_8; } -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) -{ +bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && info); @@ -253,30 +304,27 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) return true; } -bool tuh_cdc_mounted(uint8_t idx) -{ +bool tuh_cdc_mounted(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); - return p_cdc != NULL; + TU_VERIFY(p_cdc); + return p_cdc->mounted; } -bool tuh_cdc_get_dtr(uint8_t idx) -{ +bool tuh_cdc_get_dtr(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false; } -bool tuh_cdc_get_rts(uint8_t idx) -{ +bool tuh_cdc_get_rts(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false; } -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) -{ +bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -289,32 +337,28 @@ bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) // Write //--------------------------------------------------------------------+ -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) -{ +uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } -uint32_t tuh_cdc_write_flush(uint8_t idx) -{ +uint32_t tuh_cdc_write_flush(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } -bool tuh_cdc_write_clear(uint8_t idx) -{ +bool tuh_cdc_write_clear(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_clear(&p_cdc->stream.tx); } -uint32_t tuh_cdc_write_available(uint8_t idx) -{ +uint32_t tuh_cdc_write_available(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -325,32 +369,28 @@ uint32_t tuh_cdc_write_available(uint8_t idx) // Read //--------------------------------------------------------------------+ -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) -{ +uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } -uint32_t tuh_cdc_read_available(uint8_t idx) -{ +uint32_t tuh_cdc_read_available(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read_available(&p_cdc->stream.rx); } -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) -{ +bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_peek(&p_cdc->stream.rx, ch); } -bool tuh_cdc_read_clear (uint8_t idx) -{ +bool tuh_cdc_read_clear (uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -363,28 +403,25 @@ bool tuh_cdc_read_clear (uint8_t idx) // Control Endpoint API //--------------------------------------------------------------------+ -// internal control complete to update state such as line state, encoding -static void cdch_internal_control_complete(tuh_xfer_t* xfer) -{ - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); +static void process_internal_control_complete(tuh_xfer_t* xfer, uint8_t itf_num) { uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); + uint16_t const value = tu_le16toh(xfer->setup->wValue); - if (xfer->result == XFER_RESULT_SUCCESS) - { + if (xfer->result == XFER_RESULT_SUCCESS) { switch (p_cdc->serial_drid) { case SERIAL_DRIVER_ACM: switch (xfer->setup->bRequest) { case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + p_cdc->line_state = (uint8_t) value; break; case CDC_REQUEST_SET_LINE_CODING: { uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); memcpy(&p_cdc->line_coding, xfer->buffer, len); - } break; + } default: break; } @@ -394,12 +431,11 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) case SERIAL_DRIVER_FTDI: switch (xfer->setup->bRequest) { case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + p_cdc->line_state = (uint8_t) value; break; case FTDI_SIO_SET_BAUD_RATE: - // convert from divisor to baudrate is not supported - p_cdc->line_coding.bit_rate = _ftdi_requested_baud; + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; break; default: break; @@ -411,15 +447,61 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) case SERIAL_DRIVER_CP210X: switch(xfer->setup->bRequest) { case CP210X_SET_MHS: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + p_cdc->line_state = (uint8_t) value; break; case CP210X_SET_BAUDRATE: { uint32_t baudrate; memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); + break; } + + default: break; + } + break; + #endif + + #if CFG_TUH_CDC_CH34X + case SERIAL_DRIVER_CH34X: + switch (xfer->setup->bRequest) { + case CH34X_REQ_WRITE_REG: + // register write request + switch (value) { + case CH34X_REG16_DIVISOR_PRESCALER: + // baudrate + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + break; + + case CH32X_REG16_LCR2_LCR: + // data format + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + break; + + default: break; + } break; + + case CH34X_REQ_MODEM_CTRL: { + // set modem controls RTS/DTR request. Note: signals are inverted + uint16_t const modem_signal = ~value; + if (modem_signal & CH34X_BIT_RTS) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS; + } + + if (modem_signal & CH34X_BIT_DTR) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR; + } + break; + } + + default: break; } break; #endif @@ -434,14 +516,20 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) } } +// internal control complete to update state such as line state, encoding +static void cdch_internal_control_complete(tuh_xfer_t* xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + process_internal_control_complete(xfer, itf_num); +} + bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { + if (complete_cb) { return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); - }else { + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); @@ -452,7 +540,6 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - p_cdc->line_state = (uint8_t) line_state; return true; } @@ -463,9 +550,9 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { + if (complete_cb) { return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); - }else { + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); @@ -476,25 +563,23 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - p_cdc->line_coding.bit_rate = baudrate; return true; } } -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); - // only ACM support this set line coding request - TU_VERIFY(p_cdc && p_cdc->serial_drid == SERIAL_DRIVER_ACM); - TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { - return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); - }else { + if (complete_cb) { + return driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, user_data); + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = acm_set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + bool ret = driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -502,7 +587,31 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.stop_bits = stop_bits; + p_cdc->line_coding.parity = parity; + p_cdc->line_coding.data_bits = data_bits; + return true; + } +} + +bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t* p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + + if ( complete_cb ) { + return driver->set_line_coding(p_cdc, line_coding, complete_cb, user_data); + } else { + // blocking + xfer_result_t result = XFER_RESULT_INVALID; + bool ret = driver->set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + + if (user_data) { + // user_data is not NULL, return result via user_data + *((xfer_result_t*) user_data) = result; + } + TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); p_cdc->line_coding = *line_coding; return true; } @@ -512,45 +621,51 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // CLASS-USBH API //--------------------------------------------------------------------+ -void cdch_init(void) -{ +bool cdch_init(void) { + TU_LOG_DRV("sizeof(cdch_interface_t) = %u\r\n", sizeof(cdch_interface_t)); tu_memclr(cdch_data, sizeof(cdch_data)); - - for(size_t i=0; istream.tx, true, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); + p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, + p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); + p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, + p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); } + + return true; } -void cdch_close(uint8_t daddr) -{ - for(uint8_t idx=0; idxstream.tx); + tu_edpt_stream_deinit(&p_cdc->stream.rx); + } + return true; +} + +void cdch_close(uint8_t daddr) { + for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { cdch_interface_t* p_cdc = &cdch_data[idx]; - if (p_cdc->daddr == daddr) - { + if (p_cdc->daddr == daddr) { + TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx); + // Invoke application callback if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); - //tu_memclr(p_cdc, sizeof(cdch_interface_t)); p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; + p_cdc->mounted = false; tu_edpt_stream_close(&p_cdc->stream.tx); tu_edpt_stream_close(&p_cdc->stream.rx); } } } -bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ +bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // TODO handle stall response, retry failed transfer ... TU_ASSERT(event == XFER_RESULT_SUCCESS); @@ -558,41 +673,35 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc); - if ( ep_addr == p_cdc->stream.tx.ep_addr ) - { + if ( ep_addr == p_cdc->stream.tx.ep_addr ) { // invoke tx complete callback to possibly refill tx fifo if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx); - if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) - { + if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } - } - else if ( ep_addr == p_cdc->stream.rx.ep_addr ) - { - tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - + } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { #if CFG_TUH_CDC_FTDI - // FTDI reserve 2 bytes for status if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { - uint8_t status[2]; - tu_edpt_stream_read(&p_cdc->stream.rx, status, 2); - (void) status; // TODO handle status - } + // FTDI reserve 2 bytes for status + // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]}; + tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2); + }else #endif + { + tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); + } // invoke receive callback if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx); // prepare for next transfer if needed tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - }else if ( ep_addr == p_cdc->ep_notif ) - { + }else if ( ep_addr == p_cdc->ep_notif ) { // TODO handle notification endpoint - }else - { + }else { TU_ASSERT(false); } @@ -603,22 +712,15 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); - -static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) -{ - for(size_t i=0; i<2; i++) - { +static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const* desc_ep) { + for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - + TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep); - }else - { + } else { tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep); } @@ -628,49 +730,36 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ +bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; - // Only support ACM subclass + // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device - if ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) - { + if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) { return acm_open(daddr, itf_desc, max_len); } - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X - else if ( 0xff == itf_desc->bInterfaceClass ) - { + else if (SERIAL_DRIVER_COUNT > 1 && + TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { uint16_t vid, pid; TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); - #if CFG_TUH_CDC_FTDI - if (TU_FTDI_VID == vid) { - for (size_t i = 0; i < FTDI_PID_COUNT; i++) { - if (ftdi_pids[i] == pid) { - return ftdi_open(daddr, itf_desc, max_len); - } - } - } - #endif - - #if CFG_TUH_CDC_CP210X - if (TU_CP210X_VID == vid) { - for (size_t i = 0; i < CP210X_PID_COUNT; i++) { - if (cp210x_pids[i] == pid) { - return cp210x_open(daddr, itf_desc, max_len); + for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { + cdch_serial_driver_t const* driver = &serial_drivers[dr]; + for (size_t i = 0; i < driver->vid_pid_count; i++) { + if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { + return driver->open(daddr, itf_desc, max_len); } } } - #endif } - #endif return false; } static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) { + TU_LOG_DRV("CDCh Set Configure complete\r\n"); + p_cdc->mounted = true; if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx); // Prepare for incoming data @@ -680,9 +769,7 @@ static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t i usbh_driver_set_config_complete(p_cdc->daddr, itf_num); } - -bool cdch_set_config(uint8_t daddr, uint8_t itf_num) -{ +bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); @@ -711,100 +798,90 @@ enum { CONFIG_ACM_COMPLETE, }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len; +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { + uint8_t const* p_desc_end = ((uint8_t const*) itf_desc) + max_len; - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const * p_desc = tu_desc_next(itf_desc); + uint8_t const* p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { + while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { + if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; + p_cdc->acm_capability = ((cdc_desc_func_acm_t const*) p_desc)->bmCapabilities; } p_desc = tu_desc_next(p_desc); } // Open notification endpoint of control interface if any - if (itf_desc->bNumEndpoints == 1) - { + if (itf_desc->bNumEndpoints == 1) { TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc; - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); p_cdc->ep_notif = desc_ep->bEndpointAddress; p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { + if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) { // next to endpoint descriptor p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); + TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const*) p_desc)); } return true; } -static void acm_process_config(tuh_xfer_t* xfer) -{ +static void acm_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); - switch(state) - { + switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { - TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, - CONFIG_ACM_SET_LINE_CODING), ); + if (p_cdc->acm_capability.support_line_request) { + TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, CONFIG_ACM_SET_LINE_CODING),); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_SET_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + if (p_cdc->acm_capability.support_line_request) { cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE), ); + TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE),); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_COMPLETE: // itf_num+1 to account for data interface as well - set_config_complete(p_cdc, idx, itf_num+1); + set_config_complete(p_cdc, idx, itf_num + 1); break; - default: break; + default: + break; } } static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); + TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -834,7 +911,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st } static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); + TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -866,6 +943,19 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const return true; } +static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC ACM Set Data Format\r\n"); + + cdc_line_coding_t line_coding; + line_coding.bit_rate = p_cdc->line_coding.bit_rate; + line_coding.stop_bits = stop_bits; + line_coding.parity = parity; + line_coding.data_bits = data_bits; + + return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); +} + static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); cdc_line_coding_t line_coding = p_cdc->line_coding; @@ -894,8 +984,7 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("FTDI opened\r\n"); - + TU_LOG_DRV("FTDI opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair @@ -931,22 +1020,40 @@ static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint1 return tuh_control_xfer(&xfer); } -static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data); } -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n"); +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) stop_bits; + (void) parity; + (void) data_bits; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) line_coding; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } -static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) -{ +static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; uint32_t divisor; @@ -966,18 +1073,16 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) return divisor; } -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) -{ +static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); } -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); + TU_LOG_DRV("CDC FTDI Set BaudRate = %" PRIu32 ", divisor = 0x%04x\r\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; - _ftdi_requested_baud = baudrate; + p_cdc->requested_line_coding.bit_rate = baudrate; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -999,8 +1104,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_MODEM_CTRL: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); + TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); break; #else TU_ATTR_FALLTHROUGH; @@ -1061,7 +1165,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("CP210x opened\r\n"); + TU_LOG_DRV("CP210x opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair @@ -1108,17 +1212,37 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // TODO implement later + (void) p_cdc; + (void) line_coding; + (void) complete_cb; + (void) user_data; + return false; +} + static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); + TU_LOG_DRV("CDC CP210x Set BaudRate = %" PRIu32 "\r\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb ? cdch_internal_control_complete : NULL, user_data); } -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n"); +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) stop_bits; + (void) parity; + (void) data_bits; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, complete_cb ? cdch_internal_control_complete : NULL, user_data); @@ -1157,8 +1281,7 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_DTR_RTS: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); + TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); break; #else TU_ATTR_FALLTHROUGH; @@ -1174,4 +1297,374 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { #endif +//--------------------------------------------------------------------+ +// CH34x (CH340 & CH341) +//--------------------------------------------------------------------+ + +#if CFG_TUH_CDC_CH34X + +static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits); +static uint16_t ch34x_get_divisor_prescaler(uint32_t baval); + +//------------- control request -------------// + +static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value, + uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request_setup = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_VENDOR, + .direction = direction & 0x01u + }, + .bRequest = request, + .wValue = tu_htole16 (value), + .wIndex = tu_htole16 (index), + .wLength = tu_htole16 (length) + }; + + // use usbh enum buf since application variable does not live long enough + uint8_t* enum_buf = NULL; + + if (buffer && length > 0) { + enum_buf = usbh_get_enum_buf(); + if (direction == TUSB_DIR_OUT) { + tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + } + } + + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request_setup, + .buffer = enum_buf, + .complete_cb = complete_cb, + .user_data = user_data + }; + + return tuh_control_xfer(&xfer); +} + +static inline bool ch34x_control_out(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data); +} + +static inline bool ch34x_control_in(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, + uint8_t* buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, + complete_cb, user_data); +} + +static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16_t reg_value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); +} + +//static bool ch34x_read_reg_request ( cdch_interface_t* p_cdc, uint16_t reg, +// uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +//{ +// return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); +//} + +static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate); + TU_VERIFY(div_ps); + TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, + complete_cb, user_data)); + return true; +} + +//------------- Driver API -------------// + +// internal control complete to update state such as line state, encoding +static void ch34x_control_complete(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + process_internal_control_complete(xfer, 0); +} + +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.stop_bits = stop_bits; + p_cdc->requested_line_coding.parity = parity; + p_cdc->requested_line_coding.data_bits = data_bits; + + uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); + TU_VERIFY(lcr); + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.bit_rate = baudrate; + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); + + if (xfer->result == XFER_RESULT_SUCCESS) { + // stage 1 success, continue to stage 2 + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity, + p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), ); + } else { + // stage 1 failed, notify user + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } + } +} + +// 2 stages: set baudrate (stage1) + set data format (stage2) +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding = *line_coding; + p_cdc->user_control_cb = complete_cb; + + if (complete_cb) { + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, + ch34x_set_line_coding_stage1_complete, user_data)); + } else { + // sync call + xfer_result_t result; + + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.bit_rate = line_coding->bit_rate; + + // stage 2 set data format + TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits, + NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.stop_bits = line_coding->stop_bits; + p_cdc->line_coding.parity = line_coding->parity; + p_cdc->line_coding.data_bits = line_coding->data_bits; + + // update transfer result, user_data is expected to point to xfer_result_t + if (user_data) { + *((xfer_result_t*) user_data) = result; + } + } + + return true; +} + +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t control = 0; + if (line_state & CDC_CONTROL_LINE_STATE_RTS) { + control |= CH34X_BIT_RTS; + } + if (line_state & CDC_CONTROL_LINE_STATE_DTR) { + control |= CH34X_BIT_DTR; + } + + // CH34x signals are inverted + control = ~control; + + p_cdc->user_control_cb = complete_cb; + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +//------------- Enumeration -------------// +enum { + CONFIG_CH34X_READ_VERSION = 0, + CONFIG_CH34X_SERIAL_INIT, + CONFIG_CH34X_SPECIAL_REG_WRITE, + CONFIG_CH34X_FLOW_CONTROL, + CONFIG_CH34X_MODEM_CONTROL, + CONFIG_CH34X_COMPLETE +}; + +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { + // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints + TU_VERIFY (itf_desc->bNumEndpoints == 3); + TU_VERIFY (sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + + cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY (p_cdc); + + TU_LOG_DRV ("CH34x opened\r\n"); + p_cdc->serial_drid = SERIAL_DRIVER_CH34X; + + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(itf_desc); + + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + desc_ep += 2; + + // Interrupt endpoint: not used for now + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + + return true; +} + +static void ch34x_process_config(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t* p_cdc = get_itf(idx); + uintptr_t const state = xfer->user_data; + uint8_t buffer[2]; // TODO remove + TU_ASSERT (p_cdc,); + TU_ASSERT (xfer->result == XFER_RESULT_SUCCESS,); + + switch (state) { + case CONFIG_CH34X_READ_VERSION: + TU_LOG_DRV("[%u] CDCh CH34x attempt to read Chip Version\r\n", p_cdc->daddr); + TU_ASSERT (ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, ch34x_process_config, CONFIG_CH34X_SERIAL_INIT),); + break; + + case CONFIG_CH34X_SERIAL_INIT: { + // handle version read data, set CH34x line coding (incl. baudrate) + uint8_t const version = xfer->buffer[0]; + TU_LOG_DRV("[%u] CDCh CH34x Chip Version = %02x\r\n", p_cdc->daddr, version); + // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD + TU_ASSERT (version >= 0x30,); + // init CH34x with line coding + cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate); + TU_ASSERT(div_ps, ); + uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits); + TU_ASSERT(lcr, ); + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, + ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),); + break; + } + + case CONFIG_CH34X_SPECIAL_REG_WRITE: + // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver + p_cdc->line_coding = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X); + TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),); + break; + + case CONFIG_CH34X_FLOW_CONTROL: + // no hardware flow control + TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL),); + break; + + case CONFIG_CH34X_MODEM_CONTROL: + // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) + TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ch34x_process_config, CONFIG_CH34X_COMPLETE),); + break; + + case CONFIG_CH34X_COMPLETE: + set_config_complete(p_cdc, idx, itf_num); + break; + + default: + TU_ASSERT (false,); + break; + } +} + +//------------- CH34x helper -------------// + +// calculate divisor and prescaler for baudrate, return it as 16-bit combined value +static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) { + uint8_t a; + uint8_t b; + uint32_t c; + + TU_VERIFY(baval != 0 && baval <= 2000000, 0); + switch (baval) { + case 921600: + a = 0xf3; + b = 7; + break; + + case 307200: + a = 0xd9; + b = 7; + break; + + default: + if (baval > 6000000 / 255) { + b = 3; + c = 6000000; + } else if (baval > 750000 / 255) { + b = 2; + c = 750000; + } else if (baval > 93750 / 255) { + b = 1; + c = 93750; + } else { + b = 0; + c = 11719; + } + a = (uint8_t) (c / baval); + if (a == 0 || a == 0xFF) { + return 0; + } + if ((c / a - baval) > (baval - c / (a + 1))) { + a++; + } + a = (uint8_t) (256 - a); + break; + } + + // reg divisor = a, reg prescaler = b + // According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE, + // otherwise the chip will buffer data. + return (uint16_t) ((uint16_t)a << 8 | 0x80 | b); +} + +// calculate lcr value from data coding +static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { + uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; + TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0); + lcr |= (uint8_t) (data_bits - 5); + + switch(parity) { + case CDC_LINE_CODING_PARITY_NONE: + break; + + case CDC_LINE_CODING_PARITY_ODD: + lcr |= CH34X_LCR_ENABLE_PAR; + break; + + case CDC_LINE_CODING_PARITY_EVEN: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_PAR_EVEN; + break; + + case CDC_LINE_CODING_PARITY_MARK: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE; + break; + + case CDC_LINE_CODING_PARITY_SPACE: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN; + break; + + default: break; + } + + // 1.5 stop bits not supported + TU_VERIFY(stop_bits != CDC_LINE_CODING_STOP_BITS_1_5, 0); + if (stop_bits == CDC_LINE_CODING_STOP_BITS_2) { + lcr |= CH34X_LCR_STOP_BITS_2; + } + + return lcr; +} + + +#endif // CFG_TUH_CDC_CH34X + #endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.h index 19552f1e..b63dd153 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.h +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/cdc_host.h @@ -44,7 +44,7 @@ // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t //#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM -//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } //#endif // RX FIFO size @@ -148,8 +148,11 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -// Request to Set Line Coding (ACM only) -// Should only use if you don't work with serial devices such as FTDI/CP210x +// Request to set data format +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + +// Request to Set Line Coding = baudrate + data format +// Note: only implemented by ACM and CH34x, not supported by FTDI and CP210x yet bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Get Line Coding (ACM only) @@ -159,15 +162,13 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // Connect by set both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); } // Disconnect by clear both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); } @@ -191,7 +192,8 @@ TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init (void); +bool cdch_init (void); +bool cdch_deinit (void); bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ch34x.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ch34x.h new file mode 100644 index 00000000..c18066f5 --- /dev/null +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ch34x.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Heiko Kuester + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _CH34X_H_ +#define _CH34X_H_ + +// There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found +// - https://github.com/WCHSoftGroup/ch341ser_linux +// - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c +// - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uchcom.c + +// set line_coding @ enumeration +#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM +#else // this default is necessary to work properly +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +#endif + +// USB requests +#define CH34X_REQ_READ_VERSION 0x5F // dec 95 +#define CH34X_REQ_WRITE_REG 0x9A // dec 154 +#define CH34X_REQ_READ_REG 0x95 // dec 149 +#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161 +#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164 + +// registers +#define CH34X_REG_BREAK 0x05 +#define CH34X_REG_PRESCALER 0x12 +#define CH34X_REG_DIVISOR 0x13 +#define CH34X_REG_LCR 0x18 +#define CH34X_REG_LCR2 0x25 +#define CH34X_REG_MCR_MSR 0x06 +#define CH34X_REG_MCR_MSR2 0x07 +#define CH34X_NBREAK_BITS 0x01 + +#define CH341_REG_0x0F 0x0F // undocumented register +#define CH341_REG_0x2C 0x2C // undocumented register +#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) + +#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) +#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR) + +// modem control bits +#define CH34X_BIT_RTS ( 1 << 6 ) +#define CH34X_BIT_DTR ( 1 << 5 ) + +// line control bits +#define CH34X_LCR_ENABLE_RX 0x80 +#define CH34X_LCR_ENABLE_TX 0x40 +#define CH34X_LCR_MARK_SPACE 0x20 +#define CH34X_LCR_PAR_EVEN 0x10 +#define CH34X_LCR_ENABLE_PAR 0x08 +#define CH34X_LCR_PAR_MASK 0x38 // all parity bits +#define CH34X_LCR_STOP_BITS_2 0x04 +#define CH34X_LCR_CS8 0x03 +#define CH34X_LCR_CS7 0x02 +#define CH34X_LCR_CS6 0x01 +#define CH34X_LCR_CS5 0x00 +#define CH34X_LCR_CS_MASK 0x03 // all CSx bits + +#endif /* _CH34X_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/cp210x.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/cp210x.h index b0141709..2c749f52 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/cp210x.h +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/cp210x.h @@ -29,8 +29,6 @@ // https://www.silabs.com/documents/public/application-notes/AN571.pdf #define TU_CP210X_VID 0x10C4 -#define TU_CP210X_PID_LIST \ - 0xEA60, 0xEA70 /* Config request codes */ #define CP210X_IFC_ENABLE 0x00 diff --git a/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h index 6916e403..0825f071 100644 --- a/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h +++ b/test-devices/composite-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h @@ -25,11 +25,8 @@ #ifndef TUSB_FTDI_SIO_H #define TUSB_FTDI_SIO_H -// VID/PID for matching FTDI devices +// VID for matching FTDI devices #define TU_FTDI_VID 0x0403 -#define TU_FTDI_PID_LIST \ - 0x6001, 0x6006, 0x6010, 0x6011, 0x6014, 0x6015, 0x8372, 0xFBFA, \ - 0xcd18 // Commands #define FTDI_SIO_RESET 0 /* Reset the port */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu.h b/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu.h deleted file mode 100644 index 114c827b..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ - -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 0x01, - DFU_PROTOCOL_DFU = 0x02, -} dfu_protocol_type_t; - -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; - -// DFU Requests -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; - -// DFU States -typedef enum { - APP_IDLE = 0, - APP_DETACH = 1, - DFU_IDLE = 2, - DFU_DNLOAD_SYNC = 3, - DFU_DNBUSY = 4, - DFU_DNLOAD_IDLE = 5, - DFU_MANIFEST_SYNC = 6, - DFU_MANIFEST = 7, - DFU_MANIFEST_WAIT_RESET = 8, - DFU_UPLOAD_IDLE = 9, - DFU_ERROR = 10, -} dfu_state_t; - -// DFU Status -typedef enum { - DFU_STATUS_OK = 0x00, - DFU_STATUS_ERR_TARGET = 0x01, - DFU_STATUS_ERR_FILE = 0x02, - DFU_STATUS_ERR_WRITE = 0x03, - DFU_STATUS_ERR_ERASE = 0x04, - DFU_STATUS_ERR_CHECK_ERASED = 0x05, - DFU_STATUS_ERR_PROG = 0x06, - DFU_STATUS_ERR_VERIFY = 0x07, - DFU_STATUS_ERR_ADDRESS = 0x08, - DFU_STATUS_ERR_NOTDONE = 0x09, - DFU_STATUS_ERR_FIRMWARE = 0x0A, - DFU_STATUS_ERR_VENDOR = 0x0B, - DFU_STATUS_ERR_USBR = 0x0C, - DFU_STATUS_ERR_POR = 0x0D, - DFU_STATUS_ERR_UNKNOWN = 0x0E, - DFU_STATUS_ERR_STALLEDPKT = 0x0F, -} dfu_status_t; - -#define DFU_ATTR_CAN_DOWNLOAD (1u << 0) -#define DFU_ATTR_CAN_UPLOAD (1u << 1) -#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2) -#define DFU_ATTR_WILL_DETACH (1u << 3) - -// DFU Status Request Payload -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_response_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.c b/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.c deleted file mode 100644 index 464c4bd6..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_DFU) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t attrs; - uint8_t alt; - - dfu_state_t state; - dfu_status_t status; - - bool flashing_in_progress; - uint16_t block; - uint16_t length; - - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; -} dfu_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx; - -static void reset_state(void) -{ - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.flashing_in_progress = false; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout); -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -tu_static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -tu_static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -tu_static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "ERROR" }, -}; - -tu_static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -tu_static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERR_POR , .data = "errPOR" }, - { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -tu_static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_reset(uint8_t rhport) -{ - (void) rhport; - - _dfu_ctx.attrs = 0; - _dfu_ctx.alt = 0; - - reset_state(); -} - -void dfu_moded_init(void) -{ - dfu_moded_reset(0); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - - //------------- Interface (with Alt) descriptor -------------// - uint8_t const itf_num = itf_desc->bInterfaceNumber; - uint8_t alt_count = 0; - - uint16_t drv_len = 0; - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0); - - while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) - { - TU_ASSERT(max_len > drv_len, 0); - - // Alternate must have the same interface number - TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - - // Alt should increase by one every time - TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); - alt_count++; - - drv_len += tu_desc_len(itf_desc); - itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); - } - - //------------- DFU Functional descriptor -------------// - tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; - TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); - drv_len += sizeof(tusb_desc_dfu_functional_t); - - _dfu_ctx.attrs = func_desc->bAttributes; - - // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); - - if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) - { - // Standard request include GET/SET_INTERFACE - switch ( request->bRequest ) - { - case TUSB_REQ_SET_INTERFACE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // Switch Alt interface and reset state machine - _dfu_ctx.alt = (uint8_t) request->wValue; - reset_state(); - return tud_control_status(rhport, request); - } - break; - - case TUSB_REQ_GET_INTERFACE: - if(stage == CONTROL_STAGE_SETUP) - { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); - } - break; - - // unsupported request - default: return false; - } - } - else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) - { - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - - // Class request - switch ( request->bRequest ) - { - case DFU_REQUEST_DETACH: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); - } - break; - - case DFU_REQUEST_CLRSTATUS: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); - } - break; - - case DFU_REQUEST_ABORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); - } - break; - - case DFU_REQUEST_UPLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); - TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); - } - break; - - case DFU_REQUEST_DNLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); - TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - // set to true for both download and manifest - _dfu_ctx.flashing_in_progress = true; - - // save block and length for flashing - _dfu_ctx.block = request->wValue; - _dfu_ctx.length = request->wLength; - - if ( request->wLength ) - { - // Download with payload -> transition to DOWNLOAD SYNC - _dfu_ctx.state = DFU_DNLOAD_SYNC; - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); - } - else - { - // Download is complete -> transition to MANIFEST SYNC - _dfu_ctx.state = DFU_MANIFEST_SYNC; - return tud_control_status(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - switch ( _dfu_ctx.state ) - { - case DFU_DNLOAD_SYNC: - return process_download_get_status(rhport, stage, request); - break; - - case DFU_MANIFEST_SYNC: - return process_manifest_get_status(rhport, stage, request); - break; - - default: - if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); - break; - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // unsupported request - } - - return true; -} - -void tud_dfu_finish_flashing(uint8_t status) -{ - _dfu_ctx.flashing_in_progress = false; - - if ( status == DFU_STATUS_OK ) - { - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } - else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) - ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; - } - } - else - { - // failed while flashing, move to dfuError - _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = (dfu_status_t)status; - } -} - -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_DNBUSY; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); - } - else - { - next_state = DFU_DNLOAD_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); - }else - { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - } - } - - return true; -} - -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_MANIFEST; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); - } - else - { - next_state = DFU_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_MANIFEST; - tud_dfu_manifest_cb(_dfu_ctx.alt); - } - else - { - _dfu_ctx.state = DFU_IDLE; - } - } - - return true; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) -{ - dfu_status_response_t resp; - resp.bStatus = (uint8_t) status; - resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); - resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); - resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = (uint8_t) state; - resp.iString = 0; - - return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.h b/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.h deleted file mode 100644 index fecf8596..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_device.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) - #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Must be called when the application is done with flashing started by -// tud_dfu_download_cb() and tud_dfu_manifest_cb(). -// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError -void tud_dfu_finish_flashing(uint8_t status); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. - -// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) -// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. -// During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); - -// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests -// This callback could be returned before flashing op is complete (async). -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); - -// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) -// Application can do checksum, or actual flashing if buffered entire image previously. -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt); - -// Invoked when received DFU_UPLOAD request -// Application must populate data with up to length bytes and -// Return the number of written bytes -TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_detach_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c b/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c deleted file mode 100644 index 7b77b3f8..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_DFU_RUNTIME) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_rt_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void) -{ -} - -void dfu_rtd_reset(uint8_t rhport) -{ - (void) rhport; -} - -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Runtime - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - TU_LOG2(" DFU RT Request: DETACH\r\n"); - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - } - break; - - case DFU_REQUEST_GETSTATUS: - { - TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_response_t resp; - // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - TU_VERIFY(tu_memset_s(&resp, sizeof(resp), 0x00, sizeof(resp))==0); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); - } - break; - - default: - { - TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); - return false; // stall unsupported request - } - } - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h b/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h deleted file mode 100644 index babaa821..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid.h b/test-devices/composite-stm32/lib/tinyusb/class/hid/hid.h deleted file mode 100644 index fbd3eef3..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid.h +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_HID Human Interface Device (HID) - * @{ */ - -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ -/** \defgroup ClassDriver_HID_Common Common Definitions - * @{ */ - -/// USB HID Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ - uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ - - uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ - uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ - uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ - - uint8_t bReportType; /**< Type of HID class report. */ - uint16_t wReportLength; /**< the total size of the Report descriptor. */ -} tusb_hid_descriptor_hid_t; - -/// HID Subclass -typedef enum -{ - HID_SUBCLASS_NONE = 0, ///< No Subclass - HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_enum_t; - -/// HID Interface Protocol -typedef enum -{ - HID_ITF_PROTOCOL_NONE = 0, ///< None - HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_interface_protocol_enum_t; - -/// HID Descriptor Type -typedef enum -{ - HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor - HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor - HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_enum_t; - -/// HID Request Report Type -typedef enum -{ - HID_REPORT_TYPE_INVALID = 0, - HID_REPORT_TYPE_INPUT, ///< Input - HID_REPORT_TYPE_OUTPUT, ///< Output - HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; - -/// HID Class Specific Control Request -typedef enum -{ - HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report - HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle - HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol - HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report - HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle - HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_enum_t; - -/// HID Local Code -typedef enum -{ - HID_LOCAL_NotSupported = 0 , ///< NotSupported - HID_LOCAL_Arabic , ///< Arabic - HID_LOCAL_Belgian , ///< Belgian - HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual - HID_LOCAL_Canadian_French , ///< Canadian_French - HID_LOCAL_Czech_Republic , ///< Czech_Republic - HID_LOCAL_Danish , ///< Danish - HID_LOCAL_Finnish , ///< Finnish - HID_LOCAL_French , ///< French - HID_LOCAL_German , ///< German - HID_LOCAL_Greek , ///< Greek - HID_LOCAL_Hebrew , ///< Hebrew - HID_LOCAL_Hungary , ///< Hungary - HID_LOCAL_International , ///< International - HID_LOCAL_Italian , ///< Italian - HID_LOCAL_Japan_Katakana , ///< Japan_Katakana - HID_LOCAL_Korean , ///< Korean - HID_LOCAL_Latin_American , ///< Latin_American - HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch - HID_LOCAL_Norwegian , ///< Norwegian - HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) - HID_LOCAL_Poland , ///< Poland - HID_LOCAL_Portuguese , ///< Portuguese - HID_LOCAL_Russia , ///< Russia - HID_LOCAL_Slovakia , ///< Slovakia - HID_LOCAL_Spanish , ///< Spanish - HID_LOCAL_Swedish , ///< Swedish - HID_LOCAL_Swiss_French , ///< Swiss/French - HID_LOCAL_Swiss_German , ///< Swiss/German - HID_LOCAL_Switzerland , ///< Switzerland - HID_LOCAL_Taiwan , ///< Taiwan - HID_LOCAL_Turkish_Q , ///< Turkish-Q - HID_LOCAL_UK , ///< UK - HID_LOCAL_US , ///< US - HID_LOCAL_Yugoslavia , ///< Yugoslavia - HID_LOCAL_Turkish_F ///< Turkish-F -} hid_local_enum_t; - -// HID protocol value used by GetProtocol / SetProtocol -typedef enum -{ - HID_PROTOCOL_BOOT = 0, - HID_PROTOCOL_REPORT = 1 -} hid_protocol_mode_enum_t; - -/** @} */ - -//--------------------------------------------------------------------+ -// GAMEPAD -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Gamepad Gamepad - * @{ */ - -/* From https://www.kernel.org/doc/html/latest/input/gamepad.html - ____________________________ __ - / [__ZL__] [__ZR__] \ | - / [__ TL __] [__ TR __] \ | Front Triggers - __/________________________________\__ __| - / _ \ | - / /\ __ (N) \ | - / || __ |MO| __ _ _ \ | Main Pad - | <===DP===> |SE| |ST| (W) -|- (E) | | - \ || ___ ___ _ / | - /\ \/ / \ / \ (S) /\ __| - / \________ | LS | ____ | RS | ________/ \ | -| / \ \___/ / \ \___/ / \ | | Control Sticks -| / \_____/ \_____/ \ | __| -| / \ | - \_____/ \_____/ - - |________|______| |______|___________| - D-Pad Left Right Action Pad - Stick Stick - - |_____________| - Menu Pad - - Most gamepads have the following features: - - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. - - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. - - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. - - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also - provide a digital button if you press them. - - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons - are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. - - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. - */ - -/// HID Gamepad Protocol Report. -typedef struct TU_ATTR_PACKED -{ - int8_t x; ///< Delta x movement of left analog-stick - int8_t y; ///< Delta y movement of left analog-stick - int8_t z; ///< Delta z movement of right analog-joystick - int8_t rz; ///< Delta Rz movement of right analog-joystick - int8_t rx; ///< Delta Rx movement of analog left trigger - int8_t ry; ///< Delta Ry movement of analog right trigger - uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint32_t buttons; ///< Buttons mask for currently pressed buttons -}hid_gamepad_report_t; - -/// Standard Gamepad Buttons Bitmap -typedef enum -{ - GAMEPAD_BUTTON_0 = TU_BIT(0), - GAMEPAD_BUTTON_1 = TU_BIT(1), - GAMEPAD_BUTTON_2 = TU_BIT(2), - GAMEPAD_BUTTON_3 = TU_BIT(3), - GAMEPAD_BUTTON_4 = TU_BIT(4), - GAMEPAD_BUTTON_5 = TU_BIT(5), - GAMEPAD_BUTTON_6 = TU_BIT(6), - GAMEPAD_BUTTON_7 = TU_BIT(7), - GAMEPAD_BUTTON_8 = TU_BIT(8), - GAMEPAD_BUTTON_9 = TU_BIT(9), - GAMEPAD_BUTTON_10 = TU_BIT(10), - GAMEPAD_BUTTON_11 = TU_BIT(11), - GAMEPAD_BUTTON_12 = TU_BIT(12), - GAMEPAD_BUTTON_13 = TU_BIT(13), - GAMEPAD_BUTTON_14 = TU_BIT(14), - GAMEPAD_BUTTON_15 = TU_BIT(15), - GAMEPAD_BUTTON_16 = TU_BIT(16), - GAMEPAD_BUTTON_17 = TU_BIT(17), - GAMEPAD_BUTTON_18 = TU_BIT(18), - GAMEPAD_BUTTON_19 = TU_BIT(19), - GAMEPAD_BUTTON_20 = TU_BIT(20), - GAMEPAD_BUTTON_21 = TU_BIT(21), - GAMEPAD_BUTTON_22 = TU_BIT(22), - GAMEPAD_BUTTON_23 = TU_BIT(23), - GAMEPAD_BUTTON_24 = TU_BIT(24), - GAMEPAD_BUTTON_25 = TU_BIT(25), - GAMEPAD_BUTTON_26 = TU_BIT(26), - GAMEPAD_BUTTON_27 = TU_BIT(27), - GAMEPAD_BUTTON_28 = TU_BIT(28), - GAMEPAD_BUTTON_29 = TU_BIT(29), - GAMEPAD_BUTTON_30 = TU_BIT(30), - GAMEPAD_BUTTON_31 = TU_BIT(31), -}hid_gamepad_button_bm_t; - -/// Standard Gamepad Buttons Naming from Linux input event codes -/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h -#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 -#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 - -#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 -#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 - -#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 - -#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 -#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 - -#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 -#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 - -#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 -#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 -#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 -#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 -#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 -#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 -#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 -#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 -#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 -#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 - -/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -typedef enum -{ - GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED - GAMEPAD_HAT_UP = 1, ///< DPAD_UP - GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT - GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT - GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT - GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN - GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT - GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT - GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_t; - -/// @} - -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ - -/// Standard HID Boot Protocol Mouse Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ - int8_t x; /**< Current delta x movement of the mouse. */ - int8_t y; /**< Current delta y movement on the mouse. */ - int8_t wheel; /**< Current delta wheel movement on the mouse. */ - int8_t pan; // using AC Pan -} hid_mouse_report_t; - -/// Standard Mouse Buttons Bitmap -typedef enum -{ - MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button - MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button - MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button - MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, - MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, -}hid_mouse_button_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// Keyboard -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/// Standard HID Boot Protocol Keyboard Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ - uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ - uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ -} hid_keyboard_report_t; - -/// Keyboard modifier codes bitmap -typedef enum -{ - KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control - KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift - KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt - KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window - KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control - KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift - KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt - KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window -}hid_keyboard_modifier_bm_t; - -typedef enum -{ - KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED - KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED - KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED - KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode - KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode -}hid_keyboard_led_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// HID KEYCODE -//--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_ENTER 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_F16 0x6B -#define HID_KEY_F17 0x6C -#define HID_KEY_F18 0x6D -#define HID_KEY_F19 0x6E -#define HID_KEY_F20 0x6F -#define HID_KEY_F21 0x70 -#define HID_KEY_F22 0x71 -#define HID_KEY_F23 0x72 -#define HID_KEY_F24 0x73 -#define HID_KEY_EXECUTE 0x74 -#define HID_KEY_HELP 0x75 -#define HID_KEY_MENU 0x76 -#define HID_KEY_SELECT 0x77 -#define HID_KEY_STOP 0x78 -#define HID_KEY_AGAIN 0x79 -#define HID_KEY_UNDO 0x7A -#define HID_KEY_CUT 0x7B -#define HID_KEY_COPY 0x7C -#define HID_KEY_PASTE 0x7D -#define HID_KEY_FIND 0x7E -#define HID_KEY_MUTE 0x7F -#define HID_KEY_VOLUME_UP 0x80 -#define HID_KEY_VOLUME_DOWN 0x81 -#define HID_KEY_LOCKING_CAPS_LOCK 0x82 -#define HID_KEY_LOCKING_NUM_LOCK 0x83 -#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEY_KEYPAD_COMMA 0x85 -#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEY_KANJI1 0x87 -#define HID_KEY_KANJI2 0x88 -#define HID_KEY_KANJI3 0x89 -#define HID_KEY_KANJI4 0x8A -#define HID_KEY_KANJI5 0x8B -#define HID_KEY_KANJI6 0x8C -#define HID_KEY_KANJI7 0x8D -#define HID_KEY_KANJI8 0x8E -#define HID_KEY_KANJI9 0x8F -#define HID_KEY_LANG1 0x90 -#define HID_KEY_LANG2 0x91 -#define HID_KEY_LANG3 0x92 -#define HID_KEY_LANG4 0x93 -#define HID_KEY_LANG5 0x94 -#define HID_KEY_LANG6 0x95 -#define HID_KEY_LANG7 0x96 -#define HID_KEY_LANG8 0x97 -#define HID_KEY_LANG9 0x98 -#define HID_KEY_ALTERNATE_ERASE 0x99 -#define HID_KEY_SYSREQ_ATTENTION 0x9A -#define HID_KEY_CANCEL 0x9B -#define HID_KEY_CLEAR 0x9C -#define HID_KEY_PRIOR 0x9D -#define HID_KEY_RETURN 0x9E -#define HID_KEY_SEPARATOR 0x9F -#define HID_KEY_OUT 0xA0 -#define HID_KEY_OPER 0xA1 -#define HID_KEY_CLEAR_AGAIN 0xA2 -#define HID_KEY_CRSEL_PROPS 0xA3 -#define HID_KEY_EXSEL 0xA4 -// RESERVED 0xA5-DF -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 - - -//--------------------------------------------------------------------+ -// REPORT DESCRIPTOR -//--------------------------------------------------------------------+ - -//------------- ITEM & TAG -------------// -#define HID_REPORT_DATA_0(data) -#define HID_REPORT_DATA_1(data) , data -#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) -#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) - -#define HID_REPORT_ITEM(data, tag, type, size) \ - (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) - -// Report Item Types -enum { - RI_TYPE_MAIN = 0, - RI_TYPE_GLOBAL = 1, - RI_TYPE_LOCAL = 2 -}; - -//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// - -// Report Item Main group -enum { - RI_MAIN_INPUT = 8, - RI_MAIN_OUTPUT = 9, - RI_MAIN_COLLECTION = 10, - RI_MAIN_FEATURE = 11, - RI_MAIN_COLLECTION_END = 12 -}; - -#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) - -//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// -#define HID_DATA (0<<0) -#define HID_CONSTANT (1<<0) - -#define HID_ARRAY (0<<1) -#define HID_VARIABLE (1<<1) - -#define HID_ABSOLUTE (0<<2) -#define HID_RELATIVE (1<<2) - -#define HID_WRAP_NO (0<<3) -#define HID_WRAP (1<<3) - -#define HID_LINEAR (0<<4) -#define HID_NONLINEAR (1<<4) - -#define HID_PREFERRED_STATE (0<<5) -#define HID_PREFERRED_NO (1<<5) - -#define HID_NO_NULL_POSITION (0<<6) -#define HID_NULL_STATE (1<<6) - -#define HID_NON_VOLATILE (0<<7) -#define HID_VOLATILE (1<<7) - -#define HID_BITFIELD (0<<8) -#define HID_BUFFERED_BYTES (1<<8) - -//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// -enum { - HID_COLLECTION_PHYSICAL = 0, - HID_COLLECTION_APPLICATION, - HID_COLLECTION_LOGICAL, - HID_COLLECTION_REPORT, - HID_COLLECTION_NAMED_ARRAY, - HID_COLLECTION_USAGE_SWITCH, - HID_COLLECTION_USAGE_MODIFIER -}; - -//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// - -// Report Item Global group -enum { - RI_GLOBAL_USAGE_PAGE = 0, - RI_GLOBAL_LOGICAL_MIN = 1, - RI_GLOBAL_LOGICAL_MAX = 2, - RI_GLOBAL_PHYSICAL_MIN = 3, - RI_GLOBAL_PHYSICAL_MAX = 4, - RI_GLOBAL_UNIT_EXPONENT = 5, - RI_GLOBAL_UNIT = 6, - RI_GLOBAL_REPORT_SIZE = 7, - RI_GLOBAL_REPORT_ID = 8, - RI_GLOBAL_REPORT_COUNT = 9, - RI_GLOBAL_PUSH = 10, - RI_GLOBAL_POP = 11 -}; - -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) - -#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), - -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) - -#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) - -//------------- LOCAL ITEMS 6.2.2.8 -------------// - -enum { - RI_LOCAL_USAGE = 0, - RI_LOCAL_USAGE_MIN = 1, - RI_LOCAL_USAGE_MAX = 2, - RI_LOCAL_DESIGNATOR_INDEX = 3, - RI_LOCAL_DESIGNATOR_MIN = 4, - RI_LOCAL_DESIGNATOR_MAX = 5, - // 6 is reserved - RI_LOCAL_STRING_INDEX = 7, - RI_LOCAL_STRING_MIN = 8, - RI_LOCAL_STRING_MAX = 9, - RI_LOCAL_DELIMITER = 10, -}; - -#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) - -//--------------------------------------------------------------------+ -// Usage Table -//--------------------------------------------------------------------+ - -/// HID Usage Table - Table 1: Usage Page Summary -enum { - HID_USAGE_PAGE_DESKTOP = 0x01, - HID_USAGE_PAGE_SIMULATE = 0x02, - HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, - HID_USAGE_PAGE_SPORT = 0x04, - HID_USAGE_PAGE_GAME = 0x05, - HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, - HID_USAGE_PAGE_KEYBOARD = 0x07, - HID_USAGE_PAGE_LED = 0x08, - HID_USAGE_PAGE_BUTTON = 0x09, - HID_USAGE_PAGE_ORDINAL = 0x0a, - HID_USAGE_PAGE_TELEPHONY = 0x0b, - HID_USAGE_PAGE_CONSUMER = 0x0c, - HID_USAGE_PAGE_DIGITIZER = 0x0d, - HID_USAGE_PAGE_PID = 0x0f, - HID_USAGE_PAGE_UNICODE = 0x10, - HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, - HID_USAGE_PAGE_MEDICAL = 0x40, - HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 - HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 - HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, - HID_USAGE_PAGE_SCALE = 0x8d, - HID_USAGE_PAGE_MSR = 0x8e, - HID_USAGE_PAGE_CAMERA = 0x90, - HID_USAGE_PAGE_ARCADE = 0x91, - HID_USAGE_PAGE_FIDO = 0xF1D0, // FIDO alliance HID usage page - HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF -}; - -/// HID Usage Table - Table 6: Generic Desktop Page -enum { - HID_USAGE_DESKTOP_POINTER = 0x01, - HID_USAGE_DESKTOP_MOUSE = 0x02, - HID_USAGE_DESKTOP_JOYSTICK = 0x04, - HID_USAGE_DESKTOP_GAMEPAD = 0x05, - HID_USAGE_DESKTOP_KEYBOARD = 0x06, - HID_USAGE_DESKTOP_KEYPAD = 0x07, - HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, - HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, - HID_USAGE_DESKTOP_X = 0x30, - HID_USAGE_DESKTOP_Y = 0x31, - HID_USAGE_DESKTOP_Z = 0x32, - HID_USAGE_DESKTOP_RX = 0x33, - HID_USAGE_DESKTOP_RY = 0x34, - HID_USAGE_DESKTOP_RZ = 0x35, - HID_USAGE_DESKTOP_SLIDER = 0x36, - HID_USAGE_DESKTOP_DIAL = 0x37, - HID_USAGE_DESKTOP_WHEEL = 0x38, - HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, - HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, - HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, - HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, - HID_USAGE_DESKTOP_START = 0x3d, - HID_USAGE_DESKTOP_SELECT = 0x3e, - HID_USAGE_DESKTOP_VX = 0x40, - HID_USAGE_DESKTOP_VY = 0x41, - HID_USAGE_DESKTOP_VZ = 0x42, - HID_USAGE_DESKTOP_VBRX = 0x43, - HID_USAGE_DESKTOP_VBRY = 0x44, - HID_USAGE_DESKTOP_VBRZ = 0x45, - HID_USAGE_DESKTOP_VNO = 0x46, - HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, - HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, - HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, - HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, - HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, - HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, - HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, - HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, - HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, - HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, - HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, - HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, - HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, - HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, - HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, - HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, - HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, - HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, - HID_USAGE_DESKTOP_DPAD_UP = 0x90, - HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, - HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, - HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, - HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, - HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, - HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, - HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, - HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, - HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, - HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, - HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, - HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 -}; - - -/// HID Usage Table: Consumer Page (0x0C) -/// Only contains controls that supported by Windows (whole list is too long) -enum -{ - // Generic Control - HID_USAGE_CONSUMER_CONTROL = 0x0001, - - // Power Control - HID_USAGE_CONSUMER_POWER = 0x0030, - HID_USAGE_CONSUMER_RESET = 0x0031, - HID_USAGE_CONSUMER_SLEEP = 0x0032, - - // Screen Brightness - HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, - HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, - - // These HID usages operate only on mobile systems (battery powered) and - // require Windows 8 (build 8302 or greater). - HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, - HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, - HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, - HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, - - // Media Control - HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, - HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, - HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, - HID_USAGE_CONSUMER_STOP = 0x00B7, - HID_USAGE_CONSUMER_VOLUME = 0x00E0, - HID_USAGE_CONSUMER_MUTE = 0x00E2, - HID_USAGE_CONSUMER_BASS = 0x00E3, - HID_USAGE_CONSUMER_TREBLE = 0x00E4, - HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, - HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, - HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, - HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, - HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, - HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, - HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, - - // Application Launcher - HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, - HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, - HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, - HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, - - // Browser/Explorer Specific - HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, - HID_USAGE_CONSUMER_AC_HOME = 0x0223, - HID_USAGE_CONSUMER_AC_BACK = 0x0224, - HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, - HID_USAGE_CONSUMER_AC_STOP = 0x0226, - HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, - HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, - - // Mouse Horizontal scroll - HID_USAGE_CONSUMER_AC_PAN = 0x0238, -}; - -/// HID Usage Table: FIDO Alliance Page (0xF1D0) -enum -{ - HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection - HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report - HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report -}; - -/*-------------------------------------------------------------------- - * ASCII to KEYCODE Conversion - * Expand to array of [128][2] (shift, keycode) - * - * Usage: example to convert input chr into keyboard report (modifier + keycode) - * - * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; - * - * uint8_t keycode[6] = { 0 }; - * uint8_t modifier = 0; - * - * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; - * keycode[0] = conv_table[chr][1]; - * tud_hid_keyboard_report(report_id, modifier, keycode); - * - *--------------------------------------------------------------------*/ -#define HID_ASCII_TO_KEYCODE \ - {0, 0 }, /* 0x00 Null */ \ - {0, 0 }, /* 0x01 */ \ - {0, 0 }, /* 0x02 */ \ - {0, 0 }, /* 0x03 */ \ - {0, 0 }, /* 0x04 */ \ - {0, 0 }, /* 0x05 */ \ - {0, 0 }, /* 0x06 */ \ - {0, 0 }, /* 0x07 */ \ - {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ - {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ - {0, 0 }, /* 0x0B */ \ - {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_ENTER }, /* 0x0D CR */ \ - {0, 0 }, /* 0x0E */ \ - {0, 0 }, /* 0x0F */ \ - {0, 0 }, /* 0x10 */ \ - {0, 0 }, /* 0x11 */ \ - {0, 0 }, /* 0x12 */ \ - {0, 0 }, /* 0x13 */ \ - {0, 0 }, /* 0x14 */ \ - {0, 0 }, /* 0x15 */ \ - {0, 0 }, /* 0x16 */ \ - {0, 0 }, /* 0x17 */ \ - {0, 0 }, /* 0x18 */ \ - {0, 0 }, /* 0x19 */ \ - {0, 0 }, /* 0x1A */ \ - {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ - {0, 0 }, /* 0x1C */ \ - {0, 0 }, /* 0x1D */ \ - {0, 0 }, /* 0x1E */ \ - {0, 0 }, /* 0x1F */ \ - \ - {0, HID_KEY_SPACE }, /* 0x20 */ \ - {1, HID_KEY_1 }, /* 0x21 ! */ \ - {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ - {1, HID_KEY_3 }, /* 0x23 # */ \ - {1, HID_KEY_4 }, /* 0x24 $ */ \ - {1, HID_KEY_5 }, /* 0x25 % */ \ - {1, HID_KEY_7 }, /* 0x26 & */ \ - {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ - {1, HID_KEY_9 }, /* 0x28 ( */ \ - {1, HID_KEY_0 }, /* 0x29 ) */ \ - {1, HID_KEY_8 }, /* 0x2A * */ \ - {1, HID_KEY_EQUAL }, /* 0x2B + */ \ - {0, HID_KEY_COMMA }, /* 0x2C , */ \ - {0, HID_KEY_MINUS }, /* 0x2D - */ \ - {0, HID_KEY_PERIOD }, /* 0x2E . */ \ - {0, HID_KEY_SLASH }, /* 0x2F / */ \ - {0, HID_KEY_0 }, /* 0x30 0 */ \ - {0, HID_KEY_1 }, /* 0x31 1 */ \ - {0, HID_KEY_2 }, /* 0x32 2 */ \ - {0, HID_KEY_3 }, /* 0x33 3 */ \ - {0, HID_KEY_4 }, /* 0x34 4 */ \ - {0, HID_KEY_5 }, /* 0x35 5 */ \ - {0, HID_KEY_6 }, /* 0x36 6 */ \ - {0, HID_KEY_7 }, /* 0x37 7 */ \ - {0, HID_KEY_8 }, /* 0x38 8 */ \ - {0, HID_KEY_9 }, /* 0x39 9 */ \ - {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ - {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ - {1, HID_KEY_COMMA }, /* 0x3C < */ \ - {0, HID_KEY_EQUAL }, /* 0x3D = */ \ - {1, HID_KEY_PERIOD }, /* 0x3E > */ \ - {1, HID_KEY_SLASH }, /* 0x3F ? */ \ - \ - {1, HID_KEY_2 }, /* 0x40 @ */ \ - {1, HID_KEY_A }, /* 0x41 A */ \ - {1, HID_KEY_B }, /* 0x42 B */ \ - {1, HID_KEY_C }, /* 0x43 C */ \ - {1, HID_KEY_D }, /* 0x44 D */ \ - {1, HID_KEY_E }, /* 0x45 E */ \ - {1, HID_KEY_F }, /* 0x46 F */ \ - {1, HID_KEY_G }, /* 0x47 G */ \ - {1, HID_KEY_H }, /* 0x48 H */ \ - {1, HID_KEY_I }, /* 0x49 I */ \ - {1, HID_KEY_J }, /* 0x4A J */ \ - {1, HID_KEY_K }, /* 0x4B K */ \ - {1, HID_KEY_L }, /* 0x4C L */ \ - {1, HID_KEY_M }, /* 0x4D M */ \ - {1, HID_KEY_N }, /* 0x4E N */ \ - {1, HID_KEY_O }, /* 0x4F O */ \ - {1, HID_KEY_P }, /* 0x50 P */ \ - {1, HID_KEY_Q }, /* 0x51 Q */ \ - {1, HID_KEY_R }, /* 0x52 R */ \ - {1, HID_KEY_S }, /* 0x53 S */ \ - {1, HID_KEY_T }, /* 0x55 T */ \ - {1, HID_KEY_U }, /* 0x55 U */ \ - {1, HID_KEY_V }, /* 0x56 V */ \ - {1, HID_KEY_W }, /* 0x57 W */ \ - {1, HID_KEY_X }, /* 0x58 X */ \ - {1, HID_KEY_Y }, /* 0x59 Y */ \ - {1, HID_KEY_Z }, /* 0x5A Z */ \ - {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ - {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ - {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ - {1, HID_KEY_6 }, /* 0x5E ^ */ \ - {1, HID_KEY_MINUS }, /* 0x5F _ */ \ - \ - {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ - {0, HID_KEY_A }, /* 0x61 a */ \ - {0, HID_KEY_B }, /* 0x62 b */ \ - {0, HID_KEY_C }, /* 0x63 c */ \ - {0, HID_KEY_D }, /* 0x66 d */ \ - {0, HID_KEY_E }, /* 0x65 e */ \ - {0, HID_KEY_F }, /* 0x66 f */ \ - {0, HID_KEY_G }, /* 0x67 g */ \ - {0, HID_KEY_H }, /* 0x68 h */ \ - {0, HID_KEY_I }, /* 0x69 i */ \ - {0, HID_KEY_J }, /* 0x6A j */ \ - {0, HID_KEY_K }, /* 0x6B k */ \ - {0, HID_KEY_L }, /* 0x6C l */ \ - {0, HID_KEY_M }, /* 0x6D m */ \ - {0, HID_KEY_N }, /* 0x6E n */ \ - {0, HID_KEY_O }, /* 0x6F o */ \ - {0, HID_KEY_P }, /* 0x70 p */ \ - {0, HID_KEY_Q }, /* 0x71 q */ \ - {0, HID_KEY_R }, /* 0x72 r */ \ - {0, HID_KEY_S }, /* 0x73 s */ \ - {0, HID_KEY_T }, /* 0x75 t */ \ - {0, HID_KEY_U }, /* 0x75 u */ \ - {0, HID_KEY_V }, /* 0x76 v */ \ - {0, HID_KEY_W }, /* 0x77 w */ \ - {0, HID_KEY_X }, /* 0x78 x */ \ - {0, HID_KEY_Y }, /* 0x79 y */ \ - {0, HID_KEY_Z }, /* 0x7A z */ \ - {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ - {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ - {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ - {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ - {0, HID_KEY_DELETE } /* 0x7F Delete */ \ - -/*-------------------------------------------------------------------- - * KEYCODE to Ascii Conversion - * Expand to array of [128][2] (ascii without shift, ascii with shift) - * - * Usage: example to convert ascii from keycode (key) and shift modifier (shift). - * Here we assume key < 128 ( printable ) - * - * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; - * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; - * - *--------------------------------------------------------------------*/ -#define HID_KEYCODE_TO_ASCII \ - {0 , 0 }, /* 0x00 */ \ - {0 , 0 }, /* 0x01 */ \ - {0 , 0 }, /* 0x02 */ \ - {0 , 0 }, /* 0x03 */ \ - {'a' , 'A' }, /* 0x04 */ \ - {'b' , 'B' }, /* 0x05 */ \ - {'c' , 'C' }, /* 0x06 */ \ - {'d' , 'D' }, /* 0x07 */ \ - {'e' , 'E' }, /* 0x08 */ \ - {'f' , 'F' }, /* 0x09 */ \ - {'g' , 'G' }, /* 0x0a */ \ - {'h' , 'H' }, /* 0x0b */ \ - {'i' , 'I' }, /* 0x0c */ \ - {'j' , 'J' }, /* 0x0d */ \ - {'k' , 'K' }, /* 0x0e */ \ - {'l' , 'L' }, /* 0x0f */ \ - {'m' , 'M' }, /* 0x10 */ \ - {'n' , 'N' }, /* 0x11 */ \ - {'o' , 'O' }, /* 0x12 */ \ - {'p' , 'P' }, /* 0x13 */ \ - {'q' , 'Q' }, /* 0x14 */ \ - {'r' , 'R' }, /* 0x15 */ \ - {'s' , 'S' }, /* 0x16 */ \ - {'t' , 'T' }, /* 0x17 */ \ - {'u' , 'U' }, /* 0x18 */ \ - {'v' , 'V' }, /* 0x19 */ \ - {'w' , 'W' }, /* 0x1a */ \ - {'x' , 'X' }, /* 0x1b */ \ - {'y' , 'Y' }, /* 0x1c */ \ - {'z' , 'Z' }, /* 0x1d */ \ - {'1' , '!' }, /* 0x1e */ \ - {'2' , '@' }, /* 0x1f */ \ - {'3' , '#' }, /* 0x20 */ \ - {'4' , '$' }, /* 0x21 */ \ - {'5' , '%' }, /* 0x22 */ \ - {'6' , '^' }, /* 0x23 */ \ - {'7' , '&' }, /* 0x24 */ \ - {'8' , '*' }, /* 0x25 */ \ - {'9' , '(' }, /* 0x26 */ \ - {'0' , ')' }, /* 0x27 */ \ - {'\r' , '\r' }, /* 0x28 */ \ - {'\x1b', '\x1b' }, /* 0x29 */ \ - {'\b' , '\b' }, /* 0x2a */ \ - {'\t' , '\t' }, /* 0x2b */ \ - {' ' , ' ' }, /* 0x2c */ \ - {'-' , '_' }, /* 0x2d */ \ - {'=' , '+' }, /* 0x2e */ \ - {'[' , '{' }, /* 0x2f */ \ - {']' , '}' }, /* 0x30 */ \ - {'\\' , '|' }, /* 0x31 */ \ - {'#' , '~' }, /* 0x32 */ \ - {';' , ':' }, /* 0x33 */ \ - {'\'' , '\"' }, /* 0x34 */ \ - {'`' , '~' }, /* 0x35 */ \ - {',' , '<' }, /* 0x36 */ \ - {'.' , '>' }, /* 0x37 */ \ - {'/' , '?' }, /* 0x38 */ \ - \ - {0 , 0 }, /* 0x39 */ \ - {0 , 0 }, /* 0x3a */ \ - {0 , 0 }, /* 0x3b */ \ - {0 , 0 }, /* 0x3c */ \ - {0 , 0 }, /* 0x3d */ \ - {0 , 0 }, /* 0x3e */ \ - {0 , 0 }, /* 0x3f */ \ - {0 , 0 }, /* 0x40 */ \ - {0 , 0 }, /* 0x41 */ \ - {0 , 0 }, /* 0x42 */ \ - {0 , 0 }, /* 0x43 */ \ - {0 , 0 }, /* 0x44 */ \ - {0 , 0 }, /* 0x45 */ \ - {0 , 0 }, /* 0x46 */ \ - {0 , 0 }, /* 0x47 */ \ - {0 , 0 }, /* 0x48 */ \ - {0 , 0 }, /* 0x49 */ \ - {0 , 0 }, /* 0x4a */ \ - {0 , 0 }, /* 0x4b */ \ - {0 , 0 }, /* 0x4c */ \ - {0 , 0 }, /* 0x4d */ \ - {0 , 0 }, /* 0x4e */ \ - {0 , 0 }, /* 0x4f */ \ - {0 , 0 }, /* 0x50 */ \ - {0 , 0 }, /* 0x51 */ \ - {0 , 0 }, /* 0x52 */ \ - {0 , 0 }, /* 0x53 */ \ - \ - {'/' , '/' }, /* 0x54 */ \ - {'*' , '*' }, /* 0x55 */ \ - {'-' , '-' }, /* 0x56 */ \ - {'+' , '+' }, /* 0x57 */ \ - {'\r' , '\r' }, /* 0x58 */ \ - {'1' , 0 }, /* 0x59 */ \ - {'2' , 0 }, /* 0x5a */ \ - {'3' , 0 }, /* 0x5b */ \ - {'4' , 0 }, /* 0x5c */ \ - {'5' , '5' }, /* 0x5d */ \ - {'6' , 0 }, /* 0x5e */ \ - {'7' , 0 }, /* 0x5f */ \ - {'8' , 0 }, /* 0x60 */ \ - {'9' , 0 }, /* 0x61 */ \ - {'0' , 0 }, /* 0x62 */ \ - {'.' , 0 }, /* 0x63 */ \ - {0 , 0 }, /* 0x64 */ \ - {0 , 0 }, /* 0x65 */ \ - {0 , 0 }, /* 0x66 */ \ - {'=' , '=' }, /* 0x67 */ \ - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_H__ */ - -/// @} diff --git a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.c b/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.c deleted file mode 100644 index 9240fe2c..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_HID) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "hid_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t itf_protocol; // Boot mouse or keyboard - - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - uint8_t idle_rate; // up to application to handle idle rate - uint16_t report_desc_len; - - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; - - // TODO save hid descriptor since host can specifically request this after enumeration - // Note: HID descriptor may be not available from application after enumeration - tusb_hid_descriptor_hid_t const * hid_descriptor; -} hidd_interface_t; - -CFG_TUSB_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID]; - -/*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return i; - } - - return 0xFF; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t instance) -{ - uint8_t const rhport = 0; - uint8_t const ep_in = _hidd_itf[instance].ep_in; - return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in); -} - -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint16_t len) -{ - uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[instance]; - - // claim endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); - - // prepare data - if (report_id) - { - p_hid->epin_buf[0] = report_id; - TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf+1, CFG_TUD_HID_EP_BUFSIZE-1, report, len)); - len++; - }else - { - TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf, CFG_TUD_HID_EP_BUFSIZE, report, len)); - } - - return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len); -} - -uint8_t tud_hid_n_interface_protocol(uint8_t instance) -{ - return _hidd_itf[instance].itf_protocol; -} - -uint8_t tud_hid_n_get_protocol(uint8_t instance) -{ - return _hidd_itf[instance].protocol_mode; -} - -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - hid_keyboard_report_t report; - - report.modifier = modifier; - report.reserved = 0; - - if ( keycode ) - { - memcpy(report.keycode, keycode, sizeof(report.keycode)); - }else - { - tu_memclr(report.keycode, 6); - } - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, - uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - hid_mouse_report_t report = - { - .buttons = buttons, - .x = x, - .y = y, - .wheel = vertical, - .pan = horizontal - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { - hid_gamepad_report_t report = - { - .x = x, - .y = y, - .z = z, - .rz = rz, - .rx = rx, - .ry = ry, - .hat = hat, - .buttons = buttons, - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -//--------------------------------------------------------------------+ -// USBD-CLASS API -//--------------------------------------------------------------------+ -void hidd_init(void) -{ - hidd_reset(0); -} - -void hidd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(_hidd_itf, sizeof(_hidd_itf)); -} - -uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) - { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = - (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(max_len >= drv_len, 0); - - // Find available interface - hidd_interface_t * p_hid = NULL; - uint8_t hid_id; - for(hid_id=0; hid_idhid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - - p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Use offsetof to avoid pointer to the odd/misaligned address - p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); - - // Prepare for output endpoint - if (p_hid->ep_out) - { - if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) - { - TU_LOG_FAILED(); - TU_BREAKPOINT(); - } - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - //------------- STD Request -------------// - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const desc_type = tu_u16_high(request->wValue); - //uint8_t const desc_index = tu_u16_low (request->wValue); - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); - } - else - { - return false; // stall unsupported request - } - } - } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - //------------- Class Specific Request -------------// - switch( request->bRequest ) - { - case HID_REQ_CONTROL_GET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - uint16_t xferlen = 0; - - // If host request a specific Report ID, add ID to as 1 byte of response - if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) - { - *report_buf++ = report_id; - req_len--; - - xferlen++; - } - - xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); - TU_ASSERT( xferlen > 0 ); - - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } - break; - - case HID_REQ_CONTROL_SET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) - { - report_buf++; - report_len--; - } - - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); - } - break; - - case HID_REQ_CONTROL_SET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) - { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); - } - - tud_control_status(rhport, request); - } - break; - - case HID_REQ_CONTROL_GET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); - } - break; - - case HID_REQ_CONTROL_GET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); - } - break; - - case HID_REQ_CONTROL_SET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - p_hid->protocol_mode = (uint8_t) request->wValue; - if (tud_hid_set_protocol_cb) - { - tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); - } - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // stall unsupported request - } - - return true; -} - -bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t instance = 0; - hidd_interface_t * p_hid = _hidd_itf; - - // Identify which interface to use - for (instance = 0; instance < CFG_TUD_HID; instance++) - { - p_hid = &_hidd_itf[instance]; - if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; - } - TU_ASSERT(instance < CFG_TUD_HID); - - // Sent report successfully - if (ep_addr == p_hid->ep_in) - { - if (tud_hid_report_complete_cb) - { - tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes); - } - } - // Received report - else if (ep_addr == p_hid->ep_out) - { - tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, (uint16_t) xferred_bytes); - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); - } - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.h b/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.h deleted file mode 100644 index 17b24def..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_device.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_DEVICE_H_ -#define _TUSB_HID_DEVICE_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE -#endif - -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUD_HID > 1 -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tud_hid_n_interface_protocol(uint8_t instance); - -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -uint8_t tud_hid_n_get_protocol(uint8_t instance); - -// Send report to host -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint16_t len); - -// KEYBOARD: convenient helper to send keyboard report if application -// use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); - -// MOUSE: convenient helper to send mouse report if application -// use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); - -// Gamepad: convenient helper to send gamepad report if application -// use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline uint8_t tud_hid_interface_protocol(void); -static inline uint8_t tud_hid_get_protocol(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET HID REPORT DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); - -// Invoked when received SET_PROTOCOL request -// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); - -// Invoked when received SET_IDLE request. return false will stall the request -// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len); - - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void) -{ - return tud_hid_n_ready(0); -} - -static inline uint8_t tud_hid_interface_protocol(void) -{ - return tud_hid_n_interface_protocol(0); -} - -static inline uint8_t tud_hid_get_protocol(void) -{ - return tud_hid_n_get_protocol(0); -} - -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) -{ - return tud_hid_n_report(0, report_id, report, len); -} - -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); -} - -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); -} - -/* --------------------------------------------------------------------+ - * HID Report Descriptor Template - * - * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave - * empty if multiple reports is not used - * - * - Only 1 report: no parameter - * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; - * - * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template - * uint8_t const report_desc[] = - * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) - * }; - *--------------------------------------------------------------------*/ - -// Keyboard Report Descriptor Template -#define TUD_HID_REPORT_DESC_KEYBOARD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bits Modifier Keys (Shift, Control, Alt) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 224 ) ,\ - HID_USAGE_MAX ( 231 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 8 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit reserved */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_REPORT_COUNT ( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* led padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_OUTPUT ( HID_CONSTANT ) ,\ - /* 6-byte Keycodes */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX_N ( 255, 2 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N( 255, 2 ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// Mouse Report Descriptor Template -#define TUD_HID_REPORT_DESC_MOUSE(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ - HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - /* Left, Right, Middle, Backward, Forward buttons */ \ - HID_REPORT_COUNT( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 3 bit padding */ \ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - /* X, Y position [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - /* Verital wheel scroll [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ - /* Horizontal wheel scroll [-127, 127] */ \ - HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ - HID_LOGICAL_MIN ( 0x81 ), \ - HID_LOGICAL_MAX ( 0x7f ), \ - HID_REPORT_COUNT( 1 ), \ - HID_REPORT_SIZE ( 8 ), \ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ - HID_COLLECTION_END , \ - HID_COLLECTION_END \ - -// Consumer Control Report Descriptor Template -#define TUD_HID_REPORT_DESC_CONSUMER(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\ - HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_LOGICAL_MIN ( 0x00 ) ,\ - HID_LOGICAL_MAX_N( 0x03FF, 2 ) ,\ - HID_USAGE_MIN ( 0x00 ) ,\ - HID_USAGE_MAX_N ( 0x03FF, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 16 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -/* System Control Report Descriptor Template - * 0x00 - do nothing - * 0x01 - Power Off - * 0x02 - Standby - * 0x03 - Wake Host - */ -#define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 2 bit system power control */ \ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 3 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - /* 6 bit padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 6 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_COLLECTION_END \ - -// Gamepad Report Descriptor Template -// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout -// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | -#define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit DPad/Hat Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 8 ) ,\ - HID_PHYSICAL_MIN ( 0 ) ,\ - HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 32 bit Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 32 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 32 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// FIDO U2F Authenticator Descriptor Template -// - 1st parameter is report size, which is 64 bytes maximum in U2F -// - 2nd parameter is HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_FIDO_U2F(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_FIDO, 2 ) ,\ - HID_USAGE ( HID_USAGE_FIDO_U2FHID ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */ \ - __VA_ARGS__ \ - /* Usage Data In */ \ - HID_USAGE ( HID_USAGE_FIDO_DATA_IN ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_REPORT_COUNT ( report_size ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* Usage Data Out */ \ - HID_USAGE ( HID_USAGE_FIDO_DATA_OUT ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_REPORT_COUNT ( report_size ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// HID Generic Input & Output -// - 1st parameter is report size (mandatory) -// - 2nd parameter is report id HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_GENERIC_INOUT(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ - HID_USAGE ( 0x01 ),\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* Input */ \ - HID_USAGE ( 0x02 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - /* Output */ \ - HID_USAGE ( 0x03 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - HID_COLLECTION_END \ - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.c b/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.c deleted file mode 100644 index d95d3ef3..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_HID) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "hid_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t daddr; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t itf_protocol; // None, Keyboard, Mouse - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - - uint8_t report_desc_type; - uint16_t report_desc_len; - - uint16_t epin_size; - uint16_t epout_size; - - CFG_TUH_MEM_ALIGN uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; - CFG_TUH_MEM_ALIGN uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; -} hidh_interface_t; - -CFG_TUH_MEM_SECTION -tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID]; - -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline -hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) -{ - TU_ASSERT(daddr && idx < CFG_TUH_HID, NULL); - hidh_interface_t* p_hid = &_hidh_itf[idx]; - return (p_hid->daddr == daddr) ? p_hid : NULL; -} - -// Get instance ID by endpoint address -static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && - (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr) ) - { - return idx; - } - } - - return TUSB_INDEX_INVALID_8; -} - -static hidh_interface_t* find_new_itf(void) -{ - for(uint8_t i=0; idaddr = daddr; - - // re-construct descriptor - tusb_desc_interface_t* desc = &info->desc; - desc->bLength = sizeof(tusb_desc_interface_t); - desc->bDescriptorType = TUSB_DESC_INTERFACE; - - desc->bInterfaceNumber = p_hid->itf_num; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u)); - desc->bInterfaceClass = TUSB_CLASS_HID; - desc->bInterfaceSubClass = (p_hid->itf_protocol ? HID_SUBCLASS_BOOT : HID_SUBCLASS_NONE); - desc->bInterfaceProtocol = p_hid->itf_protocol; - desc->iInterface = 0; // not used yet - - return true; -} - -uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx; - } - - return TUSB_INDEX_INVALID_8; -} - -uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - return p_hid ? p_hid->itf_protocol : 0; -} - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - return p_hid ? p_hid->protocol_mode : 0; -} - -static void set_protocol_complete(tuh_xfer_t* xfer) -{ - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - if (XFER_RESULT_SUCCESS == xfer->result) - { - p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue); - } - - if (tuh_hid_set_protocol_complete_cb) - { - tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode); - } -} - -static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG2("HID Set Protocol = %d\r\n", protocol); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = itf_num, - .wLength = 0 - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid && p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE); - - return _hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0); -} - -static void set_report_complete(tuh_xfer_t* xfer) -{ - TU_LOG2("HID Set Report complete\r\n"); - - if (tuh_hid_set_report_complete_cb) - { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); - - uint8_t const report_type = tu_u16_high(xfer->setup->wValue); - uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - - tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type, - (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); - } -} - -bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_htole16(tu_u16(report_type, report_id)), - .wIndex = tu_htole16((uint16_t)p_hid->itf_num), - .wLength = len - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = report, - .complete_cb = set_report_complete, - .user_data = 0 - }; - - return tuh_control_xfer(&xfer); -} - -static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = tu_htole16(idle_rate), - .wIndex = tu_htole16((uint16_t)itf_num), - .wLength = 0 - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if HID interface is ready to receive report -bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); - TU_VERIFY(p_hid); - - return !usbh_edpt_busy(dev_addr, p_hid->ep_in); -} - -bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_in) ); - - if ( !usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size) ) - { - usbh_edpt_release(daddr, p_hid->ep_in); - return false; - } - - return true; -} - -bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); - TU_VERIFY(p_hid); - - return !usbh_edpt_busy(dev_addr, p_hid->ep_out); -} - -bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) -{ - TU_LOG2("HID Send Report %d\r\n", report_id); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - if (p_hid->ep_out == 0) - { - // This HID does not have an out endpoint (other than control) - return false; - } - else if (len > CFG_TUH_HID_EPOUT_BUFSIZE || - (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1))) - { - // ep_out buffer is not large enough to hold contents - return false; - } - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_out) ); - - if (report_id == 0) - { - // No report ID in transmission - memcpy(&p_hid->epout_buf[0], report, len); - } - else - { - p_hid->epout_buf[0] = report_id; - memcpy(&p_hid->epout_buf[1], report, len); - ++len; // 1 more byte for report_id - } - - TU_LOG3_MEM(p_hid->epout_buf, len, 2); - - if ( !usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len) ) - { - usbh_edpt_release(daddr, p_hid->ep_out); - return false; - } - - return true; -} - -//--------------------------------------------------------------------+ -// USBH API -//--------------------------------------------------------------------+ -void hidh_init(void) -{ - tu_memclr(_hidh_itf, sizeof(_hidh_itf)); -} - -bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const idx = get_idx_by_epaddr(daddr, ep_addr); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - if ( dir == TUSB_DIR_IN ) - { - TU_LOG2(" Get Report callback (%u, %u)\r\n", daddr, idx); - TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2); - tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes); - }else - { - if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes); - } - - return true; -} - -void hidh_close(uint8_t daddr) -{ - for(uint8_t i=0; idaddr == daddr) - { - if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); - p_hid->daddr = 0; - } - } -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ - -bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - - TU_LOG2("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(max_len >= drv_len); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - //------------- HID descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); - - hidh_interface_t* p_hid = find_new_itf(); - TU_ASSERT(p_hid); // not enough interface, try to increase CFG_TUH_HID - p_hid->daddr = daddr; - - //------------- Endpoint Descriptors -------------// - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - for(int i = 0; i < desc_itf->bNumEndpoints; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); - - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - p_hid->ep_in = desc_ep->bEndpointAddress; - p_hid->epin_size = tu_edpt_packet_size(desc_ep); - } - else - { - p_hid->ep_out = desc_ep->bEndpointAddress; - p_hid->epout_size = tu_edpt_packet_size(desc_ep); - } - - p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; - } - - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Assume bNumDescriptors = 1 - p_hid->report_desc_type = desc_hid->bReportType; - p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - - // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config - p_hid->protocol_mode = HID_PROTOCOL_BOOT; - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { - p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - } - - return true; -} - -//--------------------------------------------------------------------+ -// Set Configure -//--------------------------------------------------------------------+ - -enum { - CONFG_SET_IDLE, - CONFIG_SET_PROTOCOL, - CONFIG_GET_REPORT_DESC, - CONFIG_COMPLETE -}; - -static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len); -static void process_set_config(tuh_xfer_t* xfer); - -bool hidh_set_config(uint8_t daddr, uint8_t itf_num) -{ - tusb_control_request_t request; - request.wIndex = tu_htole16((uint16_t) itf_num); - - tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = CONFG_SET_IDLE; - - // fake request to kick-off the set config process - process_set_config(&xfer); - - return true; -} - -static void process_set_config(tuh_xfer_t* xfer) -{ - // Stall is a valid response for SET_IDLE, sometime SET_PROTOCOL as well - // therefore we could ignore its result - if ( !(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE || - xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL) ) - { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - } - - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; - - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - switch(state) - { - case CONFG_SET_IDLE: - { - // Idle rate = 0 mean only report when there is changes - const uint16_t idle_rate = 0; - const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; - _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state); - } - break; - - case CONFIG_SET_PROTOCOL: - _hidh_set_protocol(daddr, p_hid->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); - break; - - case CONFIG_GET_REPORT_DESC: - // Get Report Descriptor if possible - // using usbh enumeration buffer since report descriptor can be very long - if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) - { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); - - // Driver is mounted without report descriptor - config_driver_mount_complete(daddr, idx, NULL, 0); - }else - { - tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0, usbh_get_enum_buf(), p_hid->report_desc_len, process_set_config, CONFIG_COMPLETE); - } - break; - - case CONFIG_COMPLETE: - { - uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = tu_le16toh(xfer->setup->wLength); - - config_driver_mount_complete(daddr, idx, desc_report, desc_len); - } - break; - - default: break; - } -} - -static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - // enumeration is complete - if (tuh_hid_mount_cb) tuh_hid_mount_cb(daddr, idx, desc_report, desc_len); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(daddr, p_hid->itf_num); -} - -//--------------------------------------------------------------------+ -// Report Descriptor Parser -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) -{ - // Report Item 6.2.2.2 USB HID 1.11 - union TU_ATTR_PACKED - { - uint8_t byte; - struct TU_ATTR_PACKED - { - uint8_t size : 2; - uint8_t type : 2; - uint8_t tag : 4; - }; - } header; - - tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info_arr; - - // current parsed report count & size from descriptor -// uint8_t ri_report_count = 0; -// uint8_t ri_report_size = 0; - - uint8_t ri_collection_depth = 0; - - while(desc_len && report_num < arr_count) - { - header.byte = *desc_report++; - desc_len--; - - uint8_t const tag = header.tag; - uint8_t const type = header.type; - uint8_t const size = header.size; - - uint8_t const data8 = desc_report[0]; - - TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iusage_page, desc_report, size); - break; - - case RI_GLOBAL_LOGICAL_MIN : break; - case RI_GLOBAL_LOGICAL_MAX : break; - case RI_GLOBAL_PHYSICAL_MIN : break; - case RI_GLOBAL_PHYSICAL_MAX : break; - - case RI_GLOBAL_REPORT_ID: - info->report_id = data8; - break; - - case RI_GLOBAL_REPORT_SIZE: -// ri_report_size = data8; - break; - - case RI_GLOBAL_REPORT_COUNT: -// ri_report_count = data8; - break; - - case RI_GLOBAL_UNIT_EXPONENT : break; - case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_PUSH : break; - case RI_GLOBAL_POP : break; - - default: break; - } - break; - - case RI_TYPE_LOCAL: - switch(tag) - { - case RI_LOCAL_USAGE: - // only take in account the "usage" before starting REPORT ID - if ( ri_collection_depth == 0 ) info->usage = data8; - break; - - case RI_LOCAL_USAGE_MIN : break; - case RI_LOCAL_USAGE_MAX : break; - case RI_LOCAL_DESIGNATOR_INDEX : break; - case RI_LOCAL_DESIGNATOR_MIN : break; - case RI_LOCAL_DESIGNATOR_MAX : break; - case RI_LOCAL_STRING_INDEX : break; - case RI_LOCAL_STRING_MIN : break; - case RI_LOCAL_STRING_MAX : break; - case RI_LOCAL_DELIMITER : break; - default: break; - } - break; - - // error - default: break; - } - - desc_report += size; - desc_len -= size; - } - - for ( uint8_t i = 0; i < report_num; i++ ) - { - info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); - } - - return report_num; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.h b/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.h deleted file mode 100644 index 08ad421d..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/hid/hid_host.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// TODO Highspeed interrupt can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#endif - -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 -#endif - - -typedef struct -{ - uint8_t report_id; - uint8_t usage; - uint16_t usage_page; - - // TODO still use the endpoint size for now -// uint8_t in_len; // length of IN report -// uint8_t out_len; // length of OUT report -} tuh_hid_report_info_t; - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -// Get the total number of mounted HID interfaces of a device -uint8_t tuh_hid_itf_get_count(uint8_t dev_addr); - -// Get all mounted interfaces across devices -uint8_t tuh_hid_itf_get_total_count(void); - -// backward compatible rename -#define tuh_hid_instance_count tuh_hid_itf_get_count - -// Get Interface information -bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* itf_info); - -// Get Interface index from device address + interface number -// return TUSB_INDEX_INVALID_8 (0xFF) if not found -uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t idx); - -// Check if HID interface is mounted -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t idx); - -// Parse report descriptor into array of report_info struct and return number of reports. -// For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: Device will be initialized in Boot protocol for simplicity. -// Application can use set_protocol() to switch back to Report protocol. -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t idx); - -// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t idx, uint8_t protocol); - -// Set Report using control endpoint -// report_type is either Input, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if HID interface is ready to receive report -bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx); - -// Try to receive next report on Interrupt Endpoint. Immediately return -// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available -// - false if failed to queue the transfer e.g endpoint is busy -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t idx); - -// Check if HID interface is ready to send report -bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx); - -// Send report using interrupt endpoint -// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. -bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -TU_ATTR_WEAK void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len); - -// Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx); - -// Invoked when received report from device via interrupt endpoint -// Note: if there is report ID (composite), it is 1st byte of report -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); - -// Invoked when sent report to device successfully via interrupt endpoint -TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); - -// Invoked when Sent Report to device via either control endpoint -// len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); - -// Invoked when Set Protocol request is complete -TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidh_init (void); -bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_HID_HOST_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi.h b/test-devices/composite-stm32/lib/tinyusb/class/midi/midi.h deleted file mode 100644 index 8ddcdfda..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_MIDI_H__ -#define _TUSB_MIDI_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Specific Descriptor -//--------------------------------------------------------------------+ - -typedef enum -{ - MIDI_CS_INTERFACE_HEADER = 0x01, - MIDI_CS_INTERFACE_IN_JACK = 0x02, - MIDI_CS_INTERFACE_OUT_JACK = 0x03, - MIDI_CS_INTERFACE_ELEMENT = 0x04, -} midi_cs_interface_subtype_t; - -typedef enum -{ - MIDI_CS_ENDPOINT_GENERAL = 0x01 -} midi_cs_endpoint_subtype_t; - -typedef enum -{ - MIDI_JACK_EMBEDDED = 0x01, - MIDI_JACK_EXTERNAL = 0x02 -} midi_jack_type_t; - -typedef enum -{ - MIDI_CIN_MISC = 0, - MIDI_CIN_CABLE_EVENT = 1, - MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect - MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP - MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue - MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message - MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data - MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data - MIDI_CIN_NOTE_OFF = 8, - MIDI_CIN_NOTE_ON = 9, - MIDI_CIN_POLY_KEYPRESS = 10, - MIDI_CIN_CONTROL_CHANGE = 11, - MIDI_CIN_PROGRAM_CHANGE = 12, - MIDI_CIN_CHANNEL_PRESSURE = 13, - MIDI_CIN_PITCH_BEND_CHANGE = 14, - MIDI_CIN_1BYTE_DATA = 15 -} midi_code_index_number_t; - -// MIDI 1.0 status byte -enum -{ - //------------- System Exclusive -------------// - MIDI_STATUS_SYSEX_START = 0xF0, - MIDI_STATUS_SYSEX_END = 0xF7, - - //------------- System Common -------------// - MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, - MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, - MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, - // F4, F5 is undefined - MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, - - //------------- System RealTime -------------// - MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, - // 0xF9 is undefined - MIDI_STATUS_SYSREAL_START = 0xFA, - MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, - MIDI_STATUS_SYSREAL_STOP = 0xFC, - // 0xFD is undefined - MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, - MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, -}; - -/// MIDI Interface Header Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal - uint16_t wTotalLength ; -} midi_desc_header_t; - -/// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t iJack ; ///< string descriptor -} midi_desc_in_jack_t; - - -/// MIDI Out Jack Descriptor with single pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t bNrInputPins; - - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t iJack ; ///< string descriptor -} midi_desc_out_jack_t ; - -/// MIDI Out Jack Descriptor with multiple pins -#define midi_desc_out_jack_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bJackType ; \ - uint8_t bJackID ; \ - uint8_t bNrInputPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t iJack ; \ - } - -/// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bElementID; - - uint8_t bNrInputPins; - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t bNrOutputPins; - uint8_t bInTerminalLink; - uint8_t bOutTerminalLink; - uint8_t bElCapsSize; - - uint16_t bmElementCaps; - uint8_t iElement; -} midi_desc_element_t; - -/// MIDI Element Descriptor with multiple pins -#define midi_desc_element_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bDescriptorSubType; \ - uint8_t bElementID; \ - uint8_t bNrInputPins; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t bNrOutputPins; \ - uint8_t bInTerminalLink; \ - uint8_t bOutTerminalLink; \ - uint8_t bElCapsSize; \ - uint16_t bmElementCaps; \ - uint8_t iElement; \ - } - -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.c b/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.c deleted file mode 100644 index e3e7826d..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_MIDI) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "midi_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -}midid_stream_t; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - -} midid_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; - -bool tud_midi_n_mounted (uint8_t itf) -{ - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} - -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - uint8_t const rhport = 0; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= sizeof(p_midi->epout_buf) ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t const* stream = &midi->stream_read; - - // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index); -} - -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ - (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - - uint32_t total_read = 0; - while( bufsize ) - { - // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - - uint8_t const code_index = stream->buffer[0] & 0x0f; - - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; - - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; - - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; - - default: - stream->total = 3; - break; - } - } - - // Copy data up to bufsize - uint8_t const count = (uint8_t) tu_min32(stream->total - stream->index, bufsize); - - // Skip the header (1st byte) in the buffer - TU_VERIFY(0 == tu_memcpy_s(buf8, bufsize, stream->buffer + 1 + stream->index, count)); - - total_read += count; - stream->index += count; - buf8 += count; - bufsize -= count; - - // complete current event packet, reset stream - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; - } - } - - return total_read; -} - -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); - - uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(midi); - return (num_read == 4); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -static uint32_t write_flush(midid_interface_t* midi) -{ - // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) return 0; - - uint8_t const rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) - { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midid_stream_t* stream = &midi->stream_write; - - uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { - uint8_t const data = buffer[i]; - i++; - - if ( stream->index == 0 ) - { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if ( ((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - stream->total = 2; - } - else - { - stream->total = 4; - } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { - // Channel Voice Messages - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 3; - } - else if ( msg == 0xf ) - { - // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - stream->buffer[0] |= (uint8_t)(cable_num << 4); - } - else - { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } - else - { - //------------- On-going (buffering) packet -------------// - - TU_ASSERT(stream->index < 4, i); - stream->buffer[stream->index] = data; - stream->index++; - - // See if this byte ends a SysEx. - if ( (stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); - stream->total = stream->index; - } - } - - // Send out packet - if ( stream->index == stream->total ) - { - // zeroes unused bytes - for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - } - - write_flush(midi); - - return i; -} - -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); - - if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(midi); - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void midid_init(void) -{ - tu_memclr(_midid_itf, sizeof(_midid_itf)); - - for(uint8_t i=0; irx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. - - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); - #endif - } -} - -void midid_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&midi->tx_ff); - } -} - -uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); - - uint16_t drv_len = tu_desc_len(desc_itf); - uint8_t const * p_desc = tu_desc_next(desc_itf); - - // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); - - // Find available interface - midid_interface_t * p_midi = NULL; - for(uint8_t i=0; iitf_num = desc_midi->bInterfaceNumber; - (void) p_midi->itf_num; - - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } - - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // Prepare for incoming data - _prep_out_transaction(p_midi); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - (void) rhport; - (void) stage; - (void) request; - - // driver doesn't support any request yet - return false; -} - -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t itf; - midid_interface_t* p_midi; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_MIDI; itf++) - { - p_midi = &_midid_itf[itf]; - if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_MIDI); - - // receive new data - if ( ep_addr == p_midi->ep_out ) - { - tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, (uint16_t) xferred_bytes); - - // invoke receive callback if available - if (tud_midi_rx_cb) tud_midi_rx_cb(itf); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(p_midi); - } - else if ( ep_addr == p_midi->ep_in ) - { - if (0 == write_flush(p_midi)) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) - { - if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) - { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } - } - } - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.h b/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.h deleted file mode 100644 index 1c6f996b..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/midi/midi_device.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ - -#include "class/audio/audio.h" -#include "midi.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) - #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE -#endif - -#ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_MIDI > 1 -//--------------------------------------------------------------------+ - -// Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); - -// Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); - -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} - -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} - - -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} - -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ - return tud_midi_n_mounted(0); -} - -static inline uint32_t tud_midi_available (void) -{ - return tud_midi_n_available(0, 0); -} - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_read(0, 0, buffer, bufsize); -} - -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); -} - -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ - return tud_midi_n_packet_read(0, packet); -} - -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ - return tud_midi_n_packet_write(0, packet); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc.h b/test-devices/composite-stm32/lib/tinyusb/class/msc/msc.h deleted file mode 100644 index 7f25a29b..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Mass Storage Class Constant -//--------------------------------------------------------------------+ -/// MassStorage Subclass -typedef enum -{ - MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D - MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device - MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device - MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SCSI ///< SCSI transparent command set -}msc_subclass_type_t; - -enum { - MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian) - MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian) -}; - -/// \brief MassStorage Protocol. -/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy -typedef enum -{ - MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt) - MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt) - MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport -}msc_protocol_type_t; - -/// MassStorage Class-Specific Control Request -typedef enum -{ - MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15 - MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host. -}msc_request_type_t; - -/// \brief Command Block Status Values -/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed -/// successfully. A non-zero value shall indicate a failure during command execution according to the following -typedef enum -{ - MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED - MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED - MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR -}msc_csw_status_t; - -/// Command Block Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW. - uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW. - uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags. - uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host. - uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero. - uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16 - uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block -}msc_cbw_t; - -TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); - -/// Command Status Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW. - uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW. - uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device - uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t -}msc_csw_t; - -TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Constant -//--------------------------------------------------------------------+ - -/// SCSI Command Operation Code -typedef enum -{ - SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation. - SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device. - SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters. - SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command. - SCSI_CMD_START_STOP_UNIT = 0x1B, - SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, - SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device. - SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device. - SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed - SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. - SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them. -}scsi_cmd_type_t; - -/// SCSI Sense Key -typedef enum -{ - SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command - SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive. - SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed. - SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition. - SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test. - SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters - SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset. - SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed. - SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key. - SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command. - SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison. - SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium. - SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium. -}scsi_sense_key_type_t; - -//--------------------------------------------------------------------+ -// SCSI Primary Command (SPC-4) -//--------------------------------------------------------------------+ - -/// SCSI Test Unit Ready Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY - uint8_t lun ; ///< Logical Unit - uint8_t reserved[3] ; - uint8_t control ; -} scsi_test_unit_ready_t; - -TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); - -/// SCSI Inquiry Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY - uint8_t reserved1 ; - uint8_t page_code ; - uint8_t reserved2 ; - uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred. - uint8_t control ; -} scsi_inquiry_t, scsi_request_sense_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); - -/// SCSI Inquiry Response Data -typedef struct TU_ATTR_PACKED -{ - uint8_t peripheral_device_type : 5; - uint8_t peripheral_qualifier : 3; - - uint8_t : 7; - uint8_t is_removable : 1; - - uint8_t version; - - uint8_t response_data_format : 4; - uint8_t hierarchical_support : 1; - uint8_t normal_aca : 1; - uint8_t : 2; - - uint8_t additional_length; - - uint8_t protect : 1; - uint8_t : 2; - uint8_t third_party_copy : 1; - uint8_t target_port_group_support : 2; - uint8_t access_control_coordinator : 1; - uint8_t scc_support : 1; - - uint8_t addr16 : 1; - uint8_t : 3; - uint8_t multi_port : 1; - uint8_t : 1; // vendor specific - uint8_t enclosure_service : 1; - uint8_t : 1; - - uint8_t : 1; // vendor specific - uint8_t cmd_que : 1; - uint8_t : 2; - uint8_t sync : 1; - uint8_t wbus16 : 1; - uint8_t : 2; - - uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product. - uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor. - uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. -} scsi_inquiry_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); - - -typedef struct TU_ATTR_PACKED -{ - uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format - uint8_t valid : 1; - - uint8_t reserved; - - uint8_t sense_key : 4; - uint8_t : 1; - uint8_t ili : 1; ///< Incorrect length indicator - uint8_t end_of_medium : 1; - uint8_t filemark : 1; - - uint32_t information; - uint8_t add_sense_len; - uint32_t command_specific_info; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; - uint8_t field_replaceable_unit_code; - - uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout - -} scsi_sense_fixed_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6 - - uint8_t : 3; - uint8_t disable_block_descriptor : 1; - uint8_t : 4; - - uint8_t page_code : 6; - uint8_t page_control : 2; - - uint8_t subpage_code; - uint8_t alloc_length; - uint8_t control; -} scsi_mode_sense6_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); - -// This is only a Mode parameter header(6). -typedef struct TU_ATTR_PACKED -{ - uint8_t data_len; - uint8_t medium_type; - - uint8_t reserved : 7; - bool write_protected : 1; - - uint8_t block_descriptor_len; -} scsi_mode_sense6_resp_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL - uint8_t reserved[3]; - uint8_t prohibit_removal; - uint8_t control; -} scsi_prevent_allow_medium_removal_t; - -TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - - uint8_t immded : 1; - uint8_t : 7; - - uint8_t TU_RESERVED; - - uint8_t power_condition_mod : 4; - uint8_t : 4; - - uint8_t start : 1; - uint8_t load_eject : 1; - uint8_t no_flush : 1; - uint8_t : 1; - uint8_t power_condition : 4; - - uint8_t control; -} scsi_start_stop_unit_t; - -TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI MMC -//--------------------------------------------------------------------+ -/// SCSI Read Format Capacity: Write Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - uint8_t reserved[6]; - uint16_t alloc_length; - uint8_t control; -} scsi_read_format_capacity_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); - -typedef struct TU_ATTR_PACKED{ - uint8_t reserved[3]; - uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it. - - uint32_t block_num; /// Number of Logical Blocks - uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present - - uint8_t reserved2; - uint16_t block_size_u16; - -} scsi_read_format_capacity_data_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Block Command (SBC-3) -// NOTE: All data in SCSI command are in Big Endian -//--------------------------------------------------------------------+ - -/// SCSI Read Capacity 10 Command: Read Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10 - uint8_t reserved1 ; - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint16_t reserved2 ; - uint8_t partial_medium_indicator ; - uint8_t control ; -} scsi_read_capacity10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); - -/// SCSI Read Capacity 10 Response Data -typedef struct { - uint32_t last_lba ; ///< The last Logical Block Address of the device - uint32_t block_size ; ///< Block size in bytes -} scsi_read_capacity10_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); - -/// SCSI Read 10 Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode - uint8_t reserved ; // has LUN according to wiki - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint8_t reserved2 ; - uint16_t block_count ; ///< Number of Blocks used by this command - uint8_t control ; -} scsi_read10_t, scsi_write10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.c b/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.c deleted file mode 100644 index 159a1125..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_MSC) - -#include "device/dcd.h" // for faking dcd_event_xfer_complete -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "msc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Can be selectively disabled to reduce logging when troubleshooting other driver -#define MSC_DEBUG 2 - -enum -{ - MSC_STAGE_CMD = 0, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, - MSC_STAGE_STATUS_SENT, - MSC_STAGE_NEED_RESET, -}; - -typedef struct -{ - // TODO optimize alignment - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw - uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - - // Sense Response Data - uint8_t sense_key; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; -}mscd_interface_t; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); - -TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) -{ - return tu_bit_test(dir, 7); -} - -static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) -{ - // Data residue is always = host expect - actual transferred - p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - - p_msc->stage = MSC_STAGE_STATUS_SENT; - return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); -} - -static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); -} - -static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - p_csw->status = status; - p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - p_msc->stage = MSC_STAGE_STATUS; - - // failed but sense key is not set: default to Illegal Request - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - // If there is data stage and not yet complete, stall it - if ( p_cbw->total_bytes && p_csw->data_residue ) - { - if ( is_data_in(p_cbw->dir) ) - { - usbd_edpt_stall(rhport, p_msc->ep_in); - } - else - { - usbd_edpt_stall(rhport, p_msc->ep_out); - } - } -} - -static inline uint32_t rdwr10_get_lba(uint8_t const command[]) -{ - // use offsetof to avoid pointer to the odd/unaligned address - uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - - // lba is in Big Endian - return tu_ntohl(lba); -} - -static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) -{ - uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); - return tu_ntohs(block_count); -} - -static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) -{ - // first extract block count in the command - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - // invalid block count - if (block_count == 0) return 0; - - return (uint16_t) (cbw->total_bytes / block_count); -} - -uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) -{ - uint8_t status = MSC_CSW_STATUS_PASSED; - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - if ( cbw->total_bytes == 0 ) - { - if ( block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - }else - { - // no data transfer, only exist in complaint test suite - } - }else - { - if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( 0 == block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); - status = MSC_CSW_STATUS_FAILED; - } - else if ( cbw->total_bytes / block_count == 0 ) - { - TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - } - - return status; -} - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = -{ - { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, - { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, - { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, - { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, - { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, - { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent/Allow Medium Removal" }, - { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, - { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, - { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, - { .key = SCSI_CMD_READ_10 , .data = "Read10" }, - { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } -}; - -TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table = -{ - .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), - .items = _msc_scsi_cmd_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) -{ - (void) lun; - - _mscd_itf.sense_key = sense_key; - _mscd_itf.add_sense_code = add_sense_code; - _mscd_itf.add_sense_qualifier = add_sense_qualifier; - - return true; -} - -static inline void set_sense_medium_not_present(uint8_t lun) -{ - // default sense is NOT READY, MEDIUM NOT PRESENT - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void mscd_init(void) -{ - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -void mscd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // only support SCSI's BOT protocol - TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && - MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - - // Max length must be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= drv_len, 0); - - mscd_interface_t * p_msc = &_mscd_itf; - p_msc->itf_num = itf_desc->bInterfaceNumber; - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - - // Prepare for Command Block Wrapper - TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); - - return drv_len; -} - -static void proc_bot_reset(mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - p_msc->total_len = 0; - p_msc->xferred_len = 0; - - p_msc->sense_key = 0; - p_msc->add_sense_code = 0; - p_msc->add_sense_qualifier = 0; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - mscd_interface_t* p_msc = &_mscd_itf; - - // Clear Endpoint Feature (stall) for recovery - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && - TUSB_REQ_CLEAR_FEATURE == request->bRequest && - TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) - { - uint8_t const ep_addr = tu_u16_low(request->wIndex); - - if ( p_msc->stage == MSC_STAGE_NEED_RESET ) - { - // reset recovery is required to recover from this stage - // Clear Stall request cannot resolve this -> continue to stall endpoint - usbd_edpt_stall(rhport, ep_addr); - } - else - { - if ( ep_addr == p_msc->ep_in ) - { - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // resume sending SCSI status if we are in this stage previously before stalled - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - else if ( ep_addr == p_msc->ep_out ) - { - if ( p_msc->stage == MSC_STAGE_CMD ) - { - // part of reset recovery (probably due to invalid CBW) -> prepare for new command - // Note: skip if already queued previously - if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) - { - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - } - } - } - } - - return true; - } - - // From this point only handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch ( request->bRequest ) - { - case MSC_REQ_RESET: - TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 0); - - // driver state reset - proc_bot_reset(p_msc); - - tud_control_status(rhport, request); - break; - - case MSC_REQ_GET_MAX_LUN: - { - TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 1); - - uint8_t maxlun = 1; - if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); - TU_VERIFY(maxlun); - - // MAX LUN is minus 1 by specs - maxlun--; - - tud_control_xfer(rhport, request, &maxlun, 1); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) event; - - mscd_interface_t* p_msc = &_mscd_itf; - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it - if(ep_addr != p_msc->ep_out) return true; - - if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) - { - TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); - - // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery - p_msc->stage = MSC_STAGE_NEED_RESET; - - // invalid CBW stall both endpoints - usbd_edpt_stall(rhport, p_msc->ep_in); - usbd_edpt_stall(rhport, p_msc->ep_out); - - return false; - } - - TU_LOG(MSC_DEBUG, " SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); - - p_csw->signature = MSC_CSW_SIGNATURE; - p_csw->tag = p_cbw->tag; - p_csw->data_residue = 0; - p_csw->status = MSC_CSW_STATUS_PASSED; - - /*------------- Parse command and prepare DATA -------------*/ - p_msc->stage = MSC_STAGE_DATA; - p_msc->total_len = p_cbw->total_bytes; - p_msc->xferred_len = 0; - - // Read10 or Write10 - if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) - { - uint8_t const status = rdwr10_validate_cmd(p_cbw); - - if ( status != MSC_CSW_STATUS_PASSED) - { - fail_scsi_op(rhport, p_msc, status); - }else if ( p_cbw->total_bytes ) - { - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - proc_read10_cmd(rhport, p_msc); - }else - { - proc_write10_cmd(rhport, p_msc); - } - }else - { - // no data transfer, only exist in complaint test suite - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - // For other SCSI commands - // 1. OUT : queue transfer (invoke app callback after done) - // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length - if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) - { - if (p_cbw->total_bytes > sizeof(_mscd_buf)) - { - TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first - // but it is OK to just receive data then responded with failed status - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, (uint16_t) p_msc->total_len) ); - } - }else - { - // First process if it is a built-in commands - int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - - // Invoke user callback if not built-in - if ( (resplen < 0) && (p_msc->sense_key == 0) ) - { - resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); - } - - if ( resplen < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported or failed command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if (resplen == 0) - { - if (p_cbw->total_bytes) - { - // 6.7 The 13 Cases: case 4 (Hi > Dn) - // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // case 1 Hn = Dn: all good - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - if ( p_cbw->total_bytes == 0 ) - { - // 6.7 The 13 Cases: case 2 (Hn < Di) - // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // cannot return more than host expect - p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) p_msc->total_len) ); - } - } - } - } - break; - - case MSC_STAGE_DATA: - TU_LOG(MSC_DEBUG, " SCSI Data [Lun%u]\r\n", p_cbw->lun); - //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); - - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - proc_read10_cmd(rhport, p_msc); - } - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_new_data(rhport, p_msc, xferred_bytes); - } - else - { - p_msc->xferred_len += xferred_bytes; - - // OUT transfer, invoke callback if needed - if ( !is_data_in(p_cbw->dir) ) - { - int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); - - if ( cb_result < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // TODO haven't implement this scenario any further yet - } - } - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - } - else - { - // This scenario with command that take more than one transfer is already rejected at Command stage - TU_BREAKPOINT(); - } - } - break; - - case MSC_STAGE_STATUS: - // processed immediately after this switch, supposedly to be empty - break; - - case MSC_STAGE_STATUS_SENT: - // Wait for the Status phase to complete - if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) - { - TU_LOG(MSC_DEBUG, " SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status); - // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); - - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - }else - { - // Any xfer ended here is consider unknown error, ignore it - TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); - } - break; - - default : break; - } - - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // skip status if epin is currently stalled, will do it when received Clear Stall request - if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) - { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - }else - { - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(rhport, p_msc); - } - #endif - } - - return true; -} - -/*------------------------------------------------------------------*/ -/* SCSI Command Process - *------------------------------------------------------------------*/ - -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - mscd_interface_t* p_msc = &_mscd_itf; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_capa10, (size_t) resplen)); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_fmt_capa, (size_t) resplen)); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - .additional_length = sizeof(scsi_inquiry_resp_t) - 5, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &inquiry_rsp, (size_t) resplen)); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(lun); - } - - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &mode_resp, (size_t) resplen)); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, // current, fixed format - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - sense_rsp.sense_key = (uint8_t) (p_msc->sense_key & 0x0F); - sense_rsp.add_sense_code = p_msc->add_sense_code; - sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; - - resplen = sizeof(sense_rsp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &sense_rsp, (size_t) resplen)); - - // request sense callback could overwrite the sense data - if (tud_msc_request_sense_cb) - { - resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t) bufsize); - } - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Application can consume smaller bytes - uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); - - if ( nbytes < 0 ) - { - // negative means error -> endpoint is stalled & status in CSW set to failed - TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); - - // set sense - set_sense_medium_not_present(p_cbw->lun); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if ( nbytes == 0 ) - { - // zero means not ready -> simulate an transfer complete so that this driver callback will fired again - dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); - } - else - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) nbytes), ); - } -} - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - bool writable = true; - - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(p_cbw->lun); - } - - if ( !writable ) - { - // Not writable, complete this SCSI op with error - // Sense = Write protected - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - return; - } - - // remaining bytes capped at class buffer - uint16_t nbytes = (uint16_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Write10 callback will be called later when usb transfer complete - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); -} - -// process new data arrived from WRITE10 -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Invoke callback to consume new data - uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); - - if ( nbytes < 0 ) - { - // negative means error -> failed this scsi op - TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); - - // update actual byte before failed - p_msc->xferred_len += xferred_bytes; - - // Set sense - set_sense_medium_not_present(p_cbw->lun); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Application consume less than what we got (including zero) - if ( (uint32_t) nbytes < xferred_bytes ) - { - uint32_t const left_over = xferred_bytes - (uint32_t) nbytes; - if ( nbytes > 0 ) - { - p_msc->xferred_len += (uint16_t) nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, left_over); - } - - // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter - dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); - } - else - { - // Application consume all bytes in our buffer - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - // prepare to receive more data from host - proc_write10_cmd(rhport, p_msc); - } - } - } -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.h b/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.h deleted file mode 100644 index 72f95be0..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_device.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE -#endif - -#ifndef CFG_TUD_MSC_EP_BUFSIZE - #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better -#endif - -TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Set SCSI sense response -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If -// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. -// -// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If -// - write < bufsize : callback invoked again with remaining data later on. -// -// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// TODO change buffer to const uint8_t* -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); - -// Invoked when received SCSI_CMD_INQUIRY -// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun); - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); - -/** - * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE - * - READ10 and WRITE10 has their own callbacks - * - * \param[in] lun Logical unit number - * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly - * \param[out] buffer Buffer for SCSI Data Stage. - * - For INPUT: application must fill this with response. - * - For OUTPUT it holds the Data from host - * \param[in] bufsize Buffer's length. - * - * \return Actual bytes processed, can be zero for no-data command. - * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); - -/*------------- Optional callbacks -------------*/ - -// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation -TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); - -// Invoked when received REQUEST_SENSE -TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize); - -// Invoked when Read10 command is complete -TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); - -// Invoke when Write10 command is complete, can be used to flush flash caching -TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); - -// Invoked when command in tud_msc_scsi_cb is complete -TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); - -// Invoked to check if device is writable as part of SCSI WRITE10 -TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.c b/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.c deleted file mode 100644 index 1b48813e..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if CFG_TUH_ENABLED && CFG_TUH_MSC - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "msc_host.h" - -// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message -#define MSCH_DEBUG 2 - -#define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__) - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - MSC_STAGE_IDLE = 0, - MSC_STAGE_CMD, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - - volatile bool configured; // Receive SET_CONFIGURE - volatile bool mounted; // Enumeration is complete - - struct { - uint32_t block_size; - uint32_t block_count; - } capacity[CFG_TUH_MSC_MAXLUN]; - - //------------- SCSI -------------// - uint8_t stage; - void* buffer; - tuh_msc_complete_cb_t complete_cb; - uintptr_t complete_arg; - - CFG_TUH_MEM_ALIGN msc_cbw_t cbw; - CFG_TUH_MEM_ALIGN msc_csw_t csw; -}msch_interface_t; - -CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; - -// buffer used to read scsi information when mounted -// largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN -static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; -} - -//--------------------------------------------------------------------+ -// PUBLIC API -//--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->max_lun; -} - -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_count; -} - -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_size; -} - -bool tuh_msc_mounted(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted; -} - -bool tuh_msc_ready(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); -} - -//--------------------------------------------------------------------+ -// PUBLIC API: SCSI COMMAND -//--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ - tu_memclr(cbw, sizeof(msc_cbw_t)); - cbw->signature = MSC_CBW_SIGNATURE; - cbw->tag = 0x54555342; // TUSB - cbw->lun = lun; -} - -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - // TODO claim endpoint - - p_msc->cbw = *cbw; - p_msc->stage = MSC_STAGE_CMD; - p_msc->buffer = data; - p_msc->complete_cb = complete_cb; - p_msc->complete_arg = arg; - - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); - - return true; -} - -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read_capacity10_t); - cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_inquiry_t); - - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) - }; - memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification - - return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg); -} - -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); - - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; - - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); - - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg); -} - -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); - - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg); -} - -#if 0 -// MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBH API -//--------------------------------------------------------------------+ -void msch_init(void) -{ - tu_memclr(_msch_itf, sizeof(_msch_itf)); -} - -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); - - tu_memclr(p_msc, sizeof(msch_interface_t)); -} - -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - msc_cbw_t const * cbw = &p_msc->cbw; - msc_csw_t * csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - - if ( cbw->total_bytes && p_msc->buffer ) - { - // Data stage if any - p_msc->stage = MSC_STAGE_DATA; - - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; - TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes)); - }else - { - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - } - break; - - case MSC_STAGE_DATA: - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - break; - - case MSC_STAGE_STATUS: - // SCSI op is complete - p_msc->stage = MSC_STAGE_IDLE; - - if (p_msc->complete_cb) - { - tuh_msc_complete_data_t const cb_data = - { - .cbw = cbw, - .csw = csw, - .scsi_data = p_msc->buffer, - .user_arg = p_msc->complete_arg - }; - p_msc->complete_cb(dev_addr, &cb_data); - } - break; - - // unknown state - default: break; - } - - return true; -} - -//--------------------------------------------------------------------+ -// MSC Enumeration -//--------------------------------------------------------------------+ - -static void config_get_maxlun_complete (tuh_xfer_t* xfer); -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data); -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); - -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) rhport; - TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); - - // msc driver length is fixed - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(drv_len <= max_len); - - msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); - - for(uint32_t i=0; i<2; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); - - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { - p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { - p_msc->ep_out = ep_desc->bEndpointAddress; - } - - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); - } - - p_msc->itf_num = desc_itf->bInterfaceNumber; - - return true; -} - -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_ASSERT(p_msc->itf_num == itf_num); - - p_msc->configured = true; - - //------------- Get Max Lun -------------// - TU_LOG_MSCH("MSC Get Max Lun\r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 - }; - - tuh_xfer_t xfer = - { - .daddr = dev_addr, - .ep_addr = 0, - .setup = &request, - .buffer = &p_msc->max_lun, - .complete_cb = config_get_maxlun_complete, - .user_data = 0 - }; - TU_ASSERT(tuh_control_xfer(&xfer)); - - return true; -} - -static void config_get_maxlun_complete (tuh_xfer_t* xfer) -{ - uint8_t const daddr = xfer->daddr; - msch_interface_t* p_msc = get_itf(daddr); - - // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0; - p_msc->max_lun++; // MAX LUN is minus 1 by specs - - // TODO multiple LUN support - TU_LOG_MSCH("SCSI Test Unit Ready\r\n"); - uint8_t const lun = 0; - tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0); -} - -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - if (csw->status == 0) - { - // Unit is ready, read its capacity - TU_LOG_MSCH("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0); - }else - { - // Note: During enumeration, some device fails Test Unit Ready and require a few retries - // with Request Sense to start working !! - // TODO limit number of retries - TU_LOG_MSCH("SCSI Request Sense\r\n"); - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete, 0)); - } - - return true; -} - -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete, 0)); - return true; -} - -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); - p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; - p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); - - // Mark enumeration is complete - p_msc->mounted = true; - if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.h b/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.h deleted file mode 100644 index 6c0e5c9d..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/msc/msc_host.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ - -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUH_MSC_MAXLUN -#define CFG_TUH_MSC_MAXLUN 4 -#endif - -typedef struct { - msc_cbw_t const* cbw; // SCSI command - msc_csw_t const* csw; // SCSI status - void* scsi_data; // SCSI Data - uintptr_t user_arg; // user argument -}tuh_msc_complete_data_t; - -typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Check if device supports MassStorage interface. -// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() -bool tuh_msc_mounted(uint8_t dev_addr); - -// Check if the interface is currently ready or busy transferring data -bool tuh_msc_ready(uint8_t dev_addr); - -// Get Max Lun -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); - -// Get number of block -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); - -// Get block size in bytes -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); - -// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// Complete callback is invoked when SCSI op is complete. -// return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Inquiry command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Test Unit Ready command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Request Sense 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Write 10 command. Write n blocks starting from LBA to device -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by -// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -//------------- Application Callback -------------// - -// Invoked when a device with MassStorage interface is mounted -TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); - -// Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ - -void msch_init (void); -bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -void msch_close (uint8_t dev_addr); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_HOST_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/net/ecm_rndis_device.c b/test-devices/composite-stm32/lib/tinyusb/class/net/ecm_rndis_device.c deleted file mode 100644 index 8ac7cbd0..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/net/ecm_rndis_device.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( CFG_TUD_ENABLED && CFG_TUD_ECM_RNDIS ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "net_device.h" -#include "rndis_protocol.h" - -void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - bool ecm_mode; - - // Endpoint descriptor use to open/close when receiving SetInterface - // TODO since configuration descriptor may not be long-lived memory, we should - // keep a copy of endpoint attribute instead - uint8_t const * ecm_desc_epdata; - -} netd_interface_t; - -#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) -#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static -uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static -uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -tu_static const struct ecm_notify_struct ecm_notify_nc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -tu_static const struct ecm_notify_struct ecm_notify_csc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, - .wLength = 8, - }, - .downlink = 9728000, - .uplink = 9728000, -}; - -// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union -{ - uint8_t rndis_buf[120]; - struct ecm_notify_struct ecm_buf; -} notify; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// TODO remove CFG_TUSB_MEM_SECTION -CFG_TUSB_MEM_SECTION tu_static netd_interface_t _netd_itf; - -tu_static bool can_xmit; - -void tud_network_recv_renew(void) -{ - usbd_edpt_xfer(0, _netd_itf.ep_out, received, sizeof(received)); -} - -static void do_in_xfer(uint8_t *buf, uint16_t len) -{ - can_xmit = false; - usbd_edpt_xfer(0, _netd_itf.ep_in, buf, len); -} - -void netd_report(uint8_t *buf, uint16_t len) -{ - uint8_t const rhport = 0; - - // skip if previous report not yet acknowledged by host - if ( usbd_edpt_busy(rhport, _netd_itf.ep_notif) ) return; - usbd_edpt_xfer(rhport, _netd_itf.ep_notif, buf, len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void netd_init(void) -{ - tu_memclr(&_netd_itf, sizeof(_netd_itf)); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && - TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); - - TU_VERIFY(is_rndis || is_ecm, 0); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif, 0); - - // sanity check the descriptor - _netd_itf.ecm_mode = is_ecm; - - //------------- Management Interface -------------// - _netd_itf.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - RNDIS Data followed immediately by a pair of endpoints - // - CDC-ECM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for active networking - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - if ( _netd_itf.ecm_mode ) - { - // ECM by default is in-active, save the endpoint attribute - // to open later when received setInterface - _netd_itf.ecm_desc_epdata = p_desc; - }else - { - // Open endpoint pair for RNDIS - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); - - tud_network_init_cb(); - - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); - } - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ecm_report(bool nc) -{ - notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; - notify.ecm_buf.header.wIndex = _netd_itf.itf_num; - netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); - - _netd_itf.itf_data_alt = req_alt; - - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) - { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets - } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) sizeof(notify.rndis_buf)); - } - } - break; - - // unsupported request - default: return false; - } - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - } - - return true; -} - -static void handle_incoming_packet(uint32_t len) -{ - uint8_t *pnt = received; - uint32_t size = 0; - - if (_netd_itf.ecm_mode) - { - size = len; - } - else - { - rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } - } - - if (!tud_network_recv_cb(pnt, (uint16_t) size)) - { - /* if a buffer was never handled by user code, we must renew on the user's behalf */ - tud_network_recv_renew(); - } -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new packet received */ - if ( ep_addr == _netd_itf.ep_out ) - { - handle_incoming_packet(xferred_bytes); - } - - /* data transmission finished */ - if ( ep_addr == _netd_itf.ep_in ) - { - /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ - - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) - { - do_in_xfer(NULL, 0); /* a ZLP is needed */ - } - else - { - /* we're finally finished */ - can_xmit = true; - } - } - - if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) - { - if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); - } - - return true; -} - -bool tud_network_can_xmit(uint16_t size) -{ - (void)size; - - return can_xmit; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - uint8_t *data; - uint16_t len; - - if (!can_xmit) - return; - - len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; - data = transmitted + len; - - len += tud_network_xmit_cb(data, ref, arg); - - if (!_netd_itf.ecm_mode) - { - rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); - } - - do_in_xfer(transmitted, len); -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/net/ncm.h b/test-devices/composite-stm32/lib/tinyusb/class/net/ncm.h deleted file mode 100644 index 96ba11fb..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/net/ncm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// Table 4.3 Data Class Interface Protocol Codes -typedef enum -{ - NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 -} ncm_data_interface_protocol_code_t; - - -// Table 6.2 Class-Specific Request Codes for Network Control Model subclass -typedef enum -{ - NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - NCM_SET_ETHERNET_PACKET_FILTER = 0x43, - NCM_GET_ETHERNET_STATISTIC = 0x44, - NCM_GET_NTB_PARAMETERS = 0x80, - NCM_GET_NET_ADDRESS = 0x81, - NCM_SET_NET_ADDRESS = 0x82, - NCM_GET_NTB_FORMAT = 0x83, - NCM_SET_NTB_FORMAT = 0x84, - NCM_GET_NTB_INPUT_SIZE = 0x85, - NCM_SET_NTB_INPUT_SIZE = 0x86, - NCM_GET_MAX_DATAGRAM_SIZE = 0x87, - NCM_SET_MAX_DATAGRAM_SIZE = 0x88, - NCM_GET_CRC_MODE = 0x89, - NCM_SET_CRC_MODE = 0x8A, -} ncm_request_code_t; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/net/ncm_device.c b/test-devices/composite-stm32/lib/tinyusb/class/net/ncm_device.c deleted file mode 100644 index 9e958024..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/net/ncm_device.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jacob Berg Potter - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( CFG_TUD_ENABLED && CFG_TUD_NCM ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "net_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -#define NTH16_SIGNATURE 0x484D434E -#define NDP16_SIGNATURE_NCM0 0x304D434E -#define NDP16_SIGNATURE_NCM1 0x314D434E - -typedef struct TU_ATTR_PACKED -{ - uint16_t wLength; - uint16_t bmNtbFormatsSupported; - uint32_t dwNtbInMaxSize; - uint16_t wNdbInDivisor; - uint16_t wNdbInPayloadRemainder; - uint16_t wNdbInAlignment; - uint16_t wReserved; - uint32_t dwNtbOutMaxSize; - uint16_t wNdbOutDivisor; - uint16_t wNdbOutPayloadRemainder; - uint16_t wNdbOutAlignment; - uint16_t wNtbOutMaxDatagrams; -} ntb_parameters_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wHeaderLength; - uint16_t wSequence; - uint16_t wBlockLength; - uint16_t wNdpIndex; -} nth16_t; - -typedef struct TU_ATTR_PACKED -{ - uint16_t wDatagramIndex; - uint16_t wDatagramLength; -} ndp16_datagram_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wLength; - uint16_t wNextNdpIndex; - ndp16_datagram_t datagram[]; -} ndp16_t; - -typedef union TU_ATTR_PACKED { - struct { - nth16_t nth; - ndp16_t ndp; - }; - uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; -} transmit_ntb_t; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - const ndp16_t *ndp; - uint8_t num_datagrams, current_datagram_index; - - enum { - REPORT_SPEED, - REPORT_CONNECTED, - REPORT_DONE - } report_state; - bool report_pending; - - uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams - uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] - uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram - uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE - uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB - - uint16_t nth_sequence; // Sequence number counter for transmitted NTBs - - bool transferring; - -} ncm_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = { - .wLength = sizeof(ntb_parameters_t), - .bmNtbFormatsSupported = 0x01, - .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, - .wNdbInDivisor = 4, - .wNdbInPayloadRemainder = 0, - .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, - .wReserved = 0, - .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, - .wNdbOutDivisor = 4, - .wNdbOutPayloadRemainder = 0, - .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, - .wNtbOutMaxDatagrams = 0 -}; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static transmit_ntb_t transmit_ntb[2]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; - -tu_static ncm_interface_t ncm_interface; - -/* - * Set up the NTB state in ncm_interface to be ready to add datagrams. - */ -static void ncm_prepare_for_tx(void) { - ncm_interface.datagram_count = 0; - // datagrams start after all the headers - ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) - + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); -} - -/* - * If not already transmitting, start sending the current NTB to the host and swap buffers - * to start filling the other one with datagrams. - */ -static void ncm_start_tx(void) { - if (ncm_interface.transferring) { - return; - } - - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t ntb_length = ncm_interface.next_datagram_offset; - - // Fill in NTB header - ntb->nth.dwSignature = NTH16_SIGNATURE; - ntb->nth.wHeaderLength = sizeof(nth16_t); - ntb->nth.wSequence = ncm_interface.nth_sequence++; - ntb->nth.wBlockLength = ntb_length; - ntb->nth.wNdpIndex = sizeof(nth16_t); - - // Fill in NDP16 header and terminator - ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; - ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); - ntb->ndp.wNextNdpIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; - - // Kick off an endpoint transfer - usbd_edpt_xfer(0, ncm_interface.ep_in, ntb->data, ntb_length); - ncm_interface.transferring = true; - - // Swap to the other NTB and clear it out - ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; - ncm_prepare_for_tx(); -} - -tu_static struct ecm_notify_struct ncm_notify_connected = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_NETWORK_CONNECTION, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -tu_static struct ecm_notify_struct ncm_notify_speed_change = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, - .wLength = 8, - }, - .downlink = 10000000, - .uplink = 10000000, -}; - -void tud_network_recv_renew(void) -{ - if (!ncm_interface.num_datagrams) - { - usbd_edpt_xfer(0, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); - return; - } - - const ndp16_t *ndp = ncm_interface.ndp; - const int i = ncm_interface.current_datagram_index; - ncm_interface.current_datagram_index++; - ncm_interface.num_datagrams--; - - tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ - -void netd_init(void) -{ - tu_memclr(&ncm_interface, sizeof(ncm_interface)); - ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; - ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; - ncm_prepare_for_tx(); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // confirm interface hasn't already been allocated - TU_ASSERT(0 == ncm_interface.ep_notif, 0); - - //------------- Management Interface -------------// - ncm_interface.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - CDC-NCM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for transfer of NTBs - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ncm_report(void) -{ - uint8_t const rhport = 0; - if (ncm_interface.report_state == REPORT_SPEED) { - ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); - ncm_interface.report_state = REPORT_CONNECTED; - ncm_interface.report_pending = true; - } else if (ncm_interface.report_state == REPORT_CONNECTED) { - ncm_notify_connected.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); - ncm_interface.report_state = REPORT_DONE; - ncm_interface.report_pending = true; - } -} - -TU_ATTR_WEAK void tud_network_link_state_cb(bool state) -{ - (void)state; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage != CONTROL_STAGE_SETUP ) return true; - - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); - - tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); - - if (req_alt != ncm_interface.itf_data_alt) { - ncm_interface.itf_data_alt = req_alt; - - if (ncm_interface.itf_data_alt) { - if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { - tud_network_recv_renew(); // prepare for incoming datagrams - } - if (!ncm_interface.report_pending) { - ncm_report(); - } - } - - tud_network_link_state_cb(ncm_interface.itf_data_alt); - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (ncm_interface.itf_num == request->wIndex); - - if (NCM_GET_NTB_PARAMETERS == request->bRequest) - { - tud_control_xfer(rhport, request, (void*)(uintptr_t) &ntb_parameters, sizeof(ntb_parameters)); - } - - break; - - // unsupported request - default: return false; - } - - return true; -} - -static void handle_incoming_datagram(uint32_t len) -{ - uint32_t size = len; - - if (len == 0) { - return; - } - - TU_ASSERT(size >= sizeof(nth16_t), ); - - const nth16_t *hdr = (const nth16_t *)receive_ntb; - TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); - TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); - - const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); - TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); - TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); - - int num_datagrams = (ndp->wLength - 12) / 4; - ncm_interface.current_datagram_index = 0; - ncm_interface.num_datagrams = 0; - ncm_interface.ndp = ndp; - for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) - { - ncm_interface.num_datagrams++; - } - - tud_network_recv_renew(); -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new datagram receive_ntb */ - if (ep_addr == ncm_interface.ep_out ) - { - handle_incoming_datagram(xferred_bytes); - } - - /* data transmission finished */ - if (ep_addr == ncm_interface.ep_in ) - { - if (ncm_interface.transferring) { - ncm_interface.transferring = false; - } - - // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now - if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { - ncm_start_tx(); - } - } - - if (ep_addr == ncm_interface.ep_notif ) - { - ncm_interface.report_pending = false; - ncm_report(); - } - - return true; -} - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size) -{ - TU_VERIFY(ncm_interface.itf_data_alt == 1); - - if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { - TU_LOG2("NTB full [by count]\r\n"); - return false; - } - - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - if (next_datagram_offset + size > ncm_interface.ntb_in_size) { - TU_LOG2("ntb full [by size]\r\n"); - return false; - } - - return true; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - - uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); - - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; - - ncm_interface.datagram_count++; - next_datagram_offset += size; - - // round up so the next datagram is aligned correctly - next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); - next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); - - ncm_interface.next_datagram_offset = next_datagram_offset; - - ncm_start_tx(); -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/net/net_device.h b/test-devices/composite-stm32/lib/tinyusb/class/net/net_device.h deleted file mode 100644 index 39991635..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/net/net_device.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ - -#include "class/cdc/cdc.h" - -#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM -#error "Cannot enable both ECM_RNDIS and NCM network drivers" -#endif - -#include "ncm.h" - -/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ -#ifndef CFG_TUD_NET_MTU -#define CFG_TUD_NET_MTU 1514 -#endif - -#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE -#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE -#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB -#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 -#endif - -#ifndef CFG_TUD_NCM_ALIGNMENT -#define CFG_TUD_NCM_ALIGNMENT 4 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// indicate to network driver that client has finished with the packet provided to network_recv_cb() -void tud_network_recv_renew(void); - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size); - -// if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(void *ref, uint16_t arg); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(const uint8_t *src, uint16_t size); - -// client must provide this: copy from network stack packet pointer to dst -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); - -//------------- ECM/RNDIS -------------// - -// client must provide this: initialize any network state back to the beginning -void tud_network_init_cb(void); - -// client must provide this: 48-bit MAC address -// TODO removed later since it is not part of tinyusb stack -extern uint8_t tud_network_mac_address[6]; - -//------------- NCM -------------// - -// callback to client providing optional indication of internal state of network driver -void tud_network_link_state_cb(bool state); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc.h b/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc.h deleted file mode 100644 index 090ab3c4..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc.h +++ /dev/null @@ -1,318 +0,0 @@ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ - -#include "common/tusb_common.h" - - -/* Implements USBTMC Revision 1.0, April 14, 2003 - - String descriptors must have a "LANGID=0x409"/US English string. - Characters must be 0x20 (' ') to 0x7E ('~') ASCII, - But MUST not contain: "/:?\* - Also must not have leading or trailing space (' ') - Device descriptor must state USB version 0x0200 or greater - - If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. -*/ - -#define USBTMC_VERSION 0x0100 -#define USBTMC_488_VERSION 0x0100 - -typedef enum { - USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, - USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, - USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, - USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, - USBTMC_MSGID_USB488_TRIGGER = 128u, -} usbtmc_msgid_enum; - -/// \brief Message header (For BULK OUT and BULK IN); 4 bytes -typedef struct TU_ATTR_PACKED -{ - uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) - uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 - uint8_t bTagInverse ; ///< Complement of the tag - uint8_t _reserved ; ///< Must be 0x00 -} usbtmc_msg_header_t; - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint8_t data[8]; -} usbtmc_msg_generic_t; - -/* Uses on the bulk-out endpoint: */ -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int EOM : 1 ; ///< EOM set on last byte - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_request_dev_dep_out; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); - -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar - } bmTransferAttributes; - uint8_t TermChar; - uint8_t _reserved[2]; -} usbtmc_msg_request_dev_dep_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); - -/* Bulk-in headers */ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint32_t TransferSize; - struct TU_ATTR_PACKED - { - uint8_t EOM: 1; ///< Last byte of transfer is the end of the message - uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_dev_dep_msg_in_header_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); - -/* Unsupported vendor things.... Are these ever used?*/ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_out; - - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); - -// Control request type should use tusb_control_request_t - -/* -typedef struct TU_ATTR_PACKED { - struct { - unsigned int Recipient : 5 ; ///< EOM set on last byte - unsigned int Type : 2 ; ///< EOM set on last byte - unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN - } bmRequestType; - uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum - uint16_t wValue ; - uint16_t wIndex ; - uint16_t wLength ; // Number of bytes in data stage -} usbtmc_class_specific_control_req; - -*/ -// bulk-in protocol errors -enum { - USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, - USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, - USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, - USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, - USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, -}; -// built-in halt errors -enum { - USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a - /// Bulk-IN transfer is in progress -}; - -typedef enum { - USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, - USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, - USBTMC_bREQUEST_INITIATE_CLEAR = 5u, - USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, - USBTMC_bREQUEST_GET_CAPABILITIES = 7u, - - USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional - - /****** USBTMC 488 *************/ - USB488_bREQUEST_READ_STATUS_BYTE = 128u, - USB488_bREQUEST_REN_CONTROL = 160u, - USB488_bREQUEST_GO_TO_LOCAL = 161u, - USB488_bREQUEST_LOCAL_LOCKOUT = 162u, - -} usmtmc_request_type_enum; - -typedef enum { - USBTMC_STATUS_SUCCESS = 0x01, - USBTMC_STATUS_PENDING = 0x02, - USBTMC_STATUS_FAILED = 0x80, - USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, - USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, - USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83, - - /****** USBTMC 488 *************/ - USB488_STATUS_INTERRUPT_IN_BUSY = 0x20 -} usbtmc_status_enum; - -/************************************************************ - * Control Responses - */ - -typedef struct TU_ATTR_PACKED { - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - uint8_t _reserved2[6]; - uint8_t _reserved3[12]; -} usbtmc_response_capabilities_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes :1; - } bmClear; -} usbtmc_get_clear_status_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both abort bulk IN and bulk OUT -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; -} usbtmc_initiate_abort_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued - } bmAbortBulkIn; - uint8_t _reserved[2]; ///< Must be zero - uint32_t NBYTES_RXD_TXD; -} usbtmc_check_abort_bulk_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; - } bmIntfcCapabilities; - - struct TU_ATTR_PACKED - { - uint8_t canEndBulkInOnTermChar :1; - } bmDevCapabilities; - - uint8_t _reserved2[6]; - uint16_t bcdUSB488; - - struct TU_ATTR_PACKED - { - uint8_t supportsTrigger :1; - uint8_t supportsREN_GTL_LLO :1; - uint8_t is488_2 :1; - } bmIntfcCapabilities488; - - struct TU_ATTR_PACKED - { - uint8_t DT1 :1; - uint8_t RL1 :1; - uint8_t SR1 :1; - uint8_t SCPI :1; - } bmDevCapabilities488; - uint8_t _reserved3[8]; -} usbtmc_response_capabilities_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; - uint8_t statusByte; -} usbtmc_read_stb_rsp_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - struct TU_ATTR_PACKED - { - unsigned int bTag : 7; - unsigned int one : 1; - } bNotify1; - uint8_t StatusByte; -} usbtmc_read_stb_interrupt_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c b/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c deleted file mode 100644 index 4e320a77..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Nathan Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This library is not fully reentrant, though it is reentrant from the view - * of either the application layer or the USB stack. Due to its locking, - * it is not safe to call its functions from interrupts. - * - * The one exception is that its functions may not be called from the application - * until the USB stack is initialized. This should not be a problem since the - * device shouldn't be sending messages until it receives a request from the - * host. - */ - - -/* - * In the case of single-CPU "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", - * the mutex structure's main effect is to disable the USB interrupts. - * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. - */ - -//Limitations: -// "vendor-specific" commands are not handled. -// Dealing with "termchar" must be handled by the application layer, -// though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're not permitted -// in USB488, anyway. - -/* Supported: - * - * Notification pulse - * Trigger - * Read status byte (both by interrupt endpoint and control message) - * - */ - - -// TODO: -// USBTMC 3.2.2 error conditions not strictly followed -// No local lock-out, REN, or GTL. -// Clear message available status byte at the correct time? (488 4.3.1.3) -// Ability to defer status byte transmission -// Transmission of status byte in response to USB488 SRQ condition - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_USBTMC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "usbtmc_device.h" - -#ifdef xDEBUG -#include "uart_util.h" -tu_static char logMsg[150]; -#endif - -// Buffer size must be an exact multiple of the max packet size for both -// bulk (up to 64 bytes for FS, 512 bytes for HS). In addation, this driver -// imposes a minimum buffer size of 32 bytes. -#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* - * The state machine does not allow simultaneous reading and writing. This is - * consistent with USBTMC. - */ - -typedef enum -{ - STATE_CLOSED, // Endpoints have not yet been opened since USB reset - STATE_NAK, // Bulk-out endpoint is in NAK state. - STATE_IDLE, // Bulk-out endpoint is waiting for CMD. - STATE_RCV, // Bulk-out is receiving DEV_DEP message - STATE_TX_REQUESTED, - STATE_TX_INITIATED, - STATE_TX_SHORTED, - STATE_CLEARING, - STATE_ABORTING_BULK_IN, - STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted - STATE_ABORTING_BULK_OUT, - STATE_NUM_STATES -} usbtmcd_state_enum; - -#if (CFG_TUD_USBTMC_ENABLE_488) - typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; -#else - typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; -#endif - - -typedef struct -{ - volatile usbtmcd_state_enum state; - - uint8_t itf_id; - uint8_t rhport; - uint8_t ep_bulk_in; - uint8_t ep_bulk_out; - uint8_t ep_int_in; - // IN buffer is only used for first packet, not the remainder - // in order to deal with prepending header - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE]; - uint32_t ep_bulk_in_wMaxPacketSize; - // OUT buffer receives one packet at a time - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE]; - uint32_t ep_bulk_out_wMaxPacketSize; - - uint32_t transfer_size_remaining; // also used for requested length for bulk IN. - uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) - - uint8_t lastBulkOutTag; // used for aborts (mostly) - uint8_t lastBulkInTag; // used for aborts (mostly) - - uint8_t const * devInBuffer; // pointer to application-layer used for transmissions - - usbtmc_capabilities_specific_t const * capabilities; -} usbtmc_interface_state_t; - -CFG_TUSB_MEM_SECTION tu_static usbtmc_interface_state_t usbtmc_state = -{ - .itf_id = 0xFF, -}; - -// We need all headers to fit in a single packet in this implementation, 32 bytes will fit all standard USBTMC headers -TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u,"USBTMC dev buffer size too small"); - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); - -#ifndef NDEBUG -tu_static uint8_t termChar; -#endif - -tu_static uint8_t termCharRequested = false; - -#if OSAL_MUTEX_REQUIRED -static OSAL_MUTEX_DEF(usbtmcLockBuffer); -#endif -osal_mutex_t usbtmcLock; - -// Our own private lock, mostly for the state variable. -#define criticalEnter() do { (void) osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) -#define criticalLeave() do { (void) osal_mutex_unlock(usbtmcLock); } while (0) - -bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) -{ - bool ret = true; - criticalEnter(); - usbtmcd_state_enum oldState = usbtmc_state.state; - if (oldState == expectedState) - { - usbtmc_state.state = newState; - } - else - { - ret = false; - } - criticalLeave(); - return ret; -} - -// called from app -// We keep a reference to the buffer, so it MUST not change until the app is -// notified that the transfer is complete. -// length of data is specified in the hdr. - -// We can't just send the whole thing at once because we need to concatanate the -// header with the data. -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, - bool usingTermChar) -{ - const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); - -#ifndef NDEBUG - TU_ASSERT(len > 0u); - TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); - TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); - if(usingTermChar) - { - TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); - } -#endif - - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - tu_varclr(hdr); - hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; - hdr->header.bTag = usbtmc_state.lastBulkInTag; - hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); - hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = endOfMessage; - hdr->bmTransferAttributes.UsingTermChar = usingTermChar; - - // Copy in the header - const size_t headerLen = sizeof(*hdr); - const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? - len : (txBufLen - headerLen); - const size_t packetLen = headerLen + dataLen; - - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); - usbtmc_state.transfer_size_remaining = len - dataLen; - usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); - - bool stateChanged = - atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); - TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); - return true; -} - -void usbtmcd_init_cb(void) -{ - usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); -#ifndef NDEBUG -# if CFG_TUD_USBTMC_ENABLE_488 - if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); - } - // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); -# endif - if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); - } -#endif - - usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); -} - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void)rhport; - - uint16_t drv_len; - uint8_t const * p_desc; - uint8_t found_endpoints = 0; - - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); - -#ifndef NDEBUG - // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); -#endif - - TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); - - // Interface - drv_len = 0u; - p_desc = (uint8_t const *) itf_desc; - - usbtmc_state.itf_id = itf_desc->bInterfaceNumber; - usbtmc_state.rhport = rhport; - - while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) - { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; - switch(ep_desc->bmAttributes.xfer) { - case TUSB_XFER_BULK: - // Ensure buffer is an exact multiple of the maxPacketSize - TU_ASSERT((USBTMCD_BUFFER_SIZE % tu_edpt_packet_size(ep_desc)) == 0, 0); - if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) - { - usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; - usbtmc_state.ep_bulk_in_wMaxPacketSize = tu_edpt_packet_size(ep_desc); - } else { - usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; - usbtmc_state.ep_bulk_out_wMaxPacketSize = tu_edpt_packet_size(ep_desc); - } - - break; - case TUSB_XFER_INTERRUPT: -#ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); -#endif - usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; - break; - default: - TU_ASSERT(false, 0); - } - TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); - found_endpoints++; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // bulk endpoints are required, but interrupt IN is optional -#ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); - if (itf_desc->bNumEndpoints == 2) - { - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); - } - else if (itf_desc->bNumEndpoints == 3) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#if (CFG_TUD_USBTMC_ENABLE_488) - if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || - usbtmc_state.capabilities->bmDevCapabilities488.SR1) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#endif -#endif - atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_open_cb(itf_desc->iInterface); - - return drv_len; -} -// Tell USBTMC class to set its bulk-in EP to ACK so that it can -// receive USBTMC commands. -// Returns false if it was already in an ACK state or is busy -// processing a command (such as a clear). Returns true if it was -// in the NAK state and successfully transitioned to the ACK wait -// state. -bool tud_usbtmc_start_bus_read() -{ - usbtmcd_state_enum oldState = usbtmc_state.state; - switch(oldState) - { - // These may transition to IDLE - case STATE_NAK: - case STATE_ABORTING_BULK_IN_ABORTED: - TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); - break; - // When receiving, let it remain receiving - case STATE_RCV: - break; - default: - return false; - } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize)); - return true; -} - -void usbtmcd_reset_cb(uint8_t rhport) -{ - (void)rhport; - usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); - - criticalEnter(); - tu_varclr(&usbtmc_state); - usbtmc_state.capabilities = capabilities; - usbtmc_state.itf_id = 0xFFu; - criticalLeave(); -} - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); - usbtmc_state.transfer_size_sent = 0u; - - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); - - TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; - return true; -} - -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(usbtmc_state.state == STATE_RCV,true); - - bool shortPacket = (packetLen < usbtmc_state.ep_bulk_out_wMaxPacketSize); - - // Packet is to be considered complete when we get enough data or at a short packet. - bool atEnd = false; - if(len >= usbtmc_state.transfer_size_remaining || shortPacket) - { - atEnd = true; - TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); - } - - len = tu_min32(len, usbtmc_state.transfer_size_remaining); - - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - - // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) - { - // TODO: Go to an error state upon failure other than just stalling the EP? - return false; - } - - - return true; -} - -static bool handle_devMsgIn(void *data, size_t len) -{ - TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); - usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); - TU_VERIFY(stateChanged); - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - - termCharRequested = msg->bmTransferAttributes.TermCharEnabled; - -#ifndef NDEBUG - termChar = msg->TermChar; -#endif - - if(termCharRequested) - TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - - TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); - return true; -} - -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - TU_VERIFY(result == XFER_RESULT_SUCCESS); - //uart_tx_str_sync("TMC XFER CB\r\n"); - if(usbtmc_state.state == STATE_CLEARING) { - return true; /* I think we can ignore everything here */ - } - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - usbtmc_msg_generic_t *msg = NULL; - - switch(usbtmc_state.state) - { - case STATE_IDLE: - { - TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); - uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); - TU_VERIFY(msg->header.bTag == invInvTag); - TU_VERIFY(msg->header.bTag != 0x00); - - switch(msg->header.MsgID) { - case USBTMC_MSGID_DEV_DEP_MSG_OUT: - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - break; - - case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; - -#if (CFG_TUD_USBTMC_ENABLE_488) - case USBTMC_MSGID_USB488_TRIGGER: - // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); - - break; -#endif - case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: - case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - default: - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - return true; - } - case STATE_RCV: - if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - return true; - - case STATE_ABORTING_BULK_OUT: - // Should be stalled by now, shouldn't have received a packet. - return false; - - case STATE_TX_REQUESTED: - case STATE_TX_INITIATED: - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_IN_SHORTED: - case STATE_ABORTING_BULK_IN_ABORTED: - default: - return false; - } - } - else if(ep_addr == usbtmc_state.ep_bulk_in) - { - switch(usbtmc_state.state) { - case STATE_TX_SHORTED: - TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); - break; - - case STATE_TX_INITIATED: - if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf)) - { - // FIXME! This removes const below! - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, - (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); - if(((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0 )) - { - usbtmc_state.state = STATE_TX_SHORTED; - } - } - return true; - - case STATE_ABORTING_BULK_IN: - // need to send short packet (ZLP?) - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - return true; - - case STATE_ABORTING_BULK_IN_SHORTED: - /* Done. :)*/ - usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; - - default: - TU_ASSERT(false); - } - } - else if (ep_addr == usbtmc_state.ep_int_in) { - // Good? - return true; - } - return false; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA and ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_TUD_USBTMC_ENABLE_488) - uint8_t bTag; -#endif - - if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && - (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && - (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && - (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) - { - uint32_t ep_addr = (request->wIndex); - - // At this point, a transfer MAY be in progress. Based on USB spec, when clearing bulk EP HALT, - // the EP transfer buffer needs to be cleared and DTOG needs to be reset, even if - // the EP is not halted. The only USBD API interface to do this is to stall and then un-stall the EP. - if(ep_addr == usbtmc_state.ep_bulk_out) - { - criticalEnter(); - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us - criticalLeave(); - tud_usbtmc_bulkOut_clearFeature_cb(); - } - else if (ep_addr == usbtmc_state.ep_bulk_in) - { - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - tud_usbtmc_bulkIn_clearFeature_cb(); - } - else if ((usbtmc_state.ep_int_in != 0) && (ep_addr == usbtmc_state.ep_int_in)) - { - // Clearing interrupt in EP - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - } - else - { - return false; - } - return true; - } - - // Otherwise, we only handle class requests. - if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) - { - return false; - } - - // Verification that we own the interface is unneeded since it's been routed to us specifically. - - switch(request->bRequest) - { - // USBTMC required requests - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkOutTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - - // wValue is the requested bTag to abort - if(usbtmc_state.state != STATE_RCV) - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = STATE_ABORTING_BULK_OUT; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - { - usbtmc_check_abort_bulk_rsp_t rsp = { - .USBTMC_status = USBTMC_STATUS_SUCCESS, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkInTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); - // wValue is the requested bTag to abort - if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0u; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % usbtmc_state.ep_bulk_in_wMaxPacketSize) == 0) ? - STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; - criticalLeave(); - if(usbtmc_state.transfer_size_sent == 0) - { - // Send short packet, nothing is in the buffer yet - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - } - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); - } - else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) - { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 8u); - - usbtmc_check_abort_bulk_rsp_t rsp = - { - .USBTMC_status = USBTMC_STATUS_FAILED, - .bmAbortBulkIn = - { - .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) - }, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, - }; - TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); - criticalEnter(); - switch(usbtmc_state.state) - { - case STATE_ABORTING_BULK_IN_ABORTED: - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.state = STATE_IDLE; - break; - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: - rsp.USBTMC_status = USBTMC_STATUS_PENDING; - break; - default: - break; - } - criticalLeave(); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - - return true; - } - - case USBTMC_bREQUEST_INITIATE_CLEAR: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the - // control endpoint response shown in Table 31, and clear all input buffers and output buffers. - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - usbtmc_state.transfer_size_remaining = 0; - criticalEnter(); - usbtmc_state.state = STATE_CLEARING; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); - return true; - } - - case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - - if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) - { - // Stuff stuck in TX buffer? - clearStatusRsp.bmClear.BulkInFifoBytes = 1; - clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; - } - else - { - // Let app check if it's clear - TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); - } - if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) - { - criticalEnter(); - usbtmc_state.state = STATE_IDLE; - criticalLeave(); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); - return true; - } - - case USBTMC_bREQUEST_GET_CAPABILITIES: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); - return true; - } - // USBTMC Optional Requests - - case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); - return true; - } -#if (CFG_TUD_USBTMC_ENABLE_488) - - // USB488 required requests - case USB488_bREQUEST_READ_STATUS_BYTE: - { - usbtmc_read_stb_rsp_488_t rsp; - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero (USB488v1.0 Table 11) - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) - { - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. Must be 0x00 (USB488v1.0 4.3.1.2) - if(usbd_edpt_busy(rhport, usbtmc_state.ep_int_in)) - { - rsp.USBTMC_status = USB488_STATUS_INTERRUPT_IN_BUSY; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_read_stb_interrupt_488_t intMsg = - { - .bNotify1 = { - .one = 1, - .bTag = bTag & 0x7Fu, - }, - .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) - }; - // Must be queued before control request response sent (USB488v1.0 4.3.1.2) - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); - } - } - else - { - rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; - } - // USB488 optional requests - case USB488_bREQUEST_REN_CONTROL: - case USB488_bREQUEST_GO_TO_LOCAL: - case USB488_bREQUEST_LOCAL_LOCKOUT: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - return false; - } -#endif - - default: - return false; - } -} - -#endif /* CFG_TUD_TSMC */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h b/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h deleted file mode 100644 index c1298ddb..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ -#define CLASS_USBTMC_USBTMC_DEVICE_H_ - -#include "usbtmc.h" - -// Enable 488 mode by default -#if !defined(CFG_TUD_USBTMC_ENABLE_488) -#define CFG_TUD_USBTMC_ENABLE_488 (1) -#endif - -/*********************************************** - * Functions to be implemented by the class implementation - */ - -// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_open_cb -// * tud_usbtmc_msg_data_cb -// * tud_usbtmc_msgBulkIn_complete_cb -// * tud_usbtmc_msg_trigger_cb -// * (successful) tud_usbtmc_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_bulkOut_clearFeature_cb - -#if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); -#else -usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); -#endif - -void tud_usbtmc_open_cb(uint8_t interface_id); - -bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); -// transfer_complete does not imply that a message is complete. -bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_msgBulkIn_complete_cb(void); -void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); - -bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); - -// Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); - -#if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); -#endif - -/******************************************* - * Called from app - * - * We keep a reference to the buffer, so it MUST not change until the app is - * notified that the transfer is complete. - ******************************************/ - -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, bool usingTermChar); - -bool tud_usbtmc_start_bus_read(void); - - -/* "callbacks" from USB device core */ - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); - -/************************************************************ - * USBTMC Descriptor Templates - *************************************************************/ - - -#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.c b/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.c deleted file mode 100644 index 93596ee3..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_VENDOR) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "vendor_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; -} vendord_interface_t; - -CFG_TUSB_MEM_SECTION tu_static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; - -#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) - - -bool tud_vendor_n_mounted (uint8_t itf) -{ - return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; -} - -uint32_t tud_vendor_n_available (uint8_t itf) -{ - return tu_fifo_count(&_vendord_itf[itf].rx_ff); -} - -bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) -{ - return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); -} - -//--------------------------------------------------------------------+ -// Read API -//--------------------------------------------------------------------+ -static void _prep_out_transaction (vendord_interface_t* p_itf) -{ - uint8_t const rhport = 0; - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_itf->ep_out), ); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); - if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) - { - usbd_edpt_xfer(rhport, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); - } - else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_itf->ep_out); - } -} - -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, (uint16_t) bufsize); - _prep_out_transaction(p_itf); - return num_read; -} - -void tud_vendor_n_read_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - tu_fifo_clear(&p_itf->rx_ff); - _prep_out_transaction(p_itf); -} - -//--------------------------------------------------------------------+ -// Write API -//--------------------------------------------------------------------+ -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, (uint16_t) bufsize); - - // flush if queue more than packet size - if (tu_fifo_count(&p_itf->tx_ff) >= CFG_TUD_VENDOR_EPSIZE) { - tud_vendor_n_write_flush(itf); - } - return ret; -} - -uint32_t tud_vendor_n_write_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); - - // No data to send - if ( !tu_fifo_count(&p_itf->tx_ff) ) return 0; - - uint8_t const rhport = 0; - - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_itf->ep_in), 0 ); - - // Pull data from FIFO - uint16_t const count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, sizeof(p_itf->epin_buf)); - - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_itf->ep_in, p_itf->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_itf->ep_in); - return 0; - } -} - -uint32_t tud_vendor_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_vendord_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void vendord_init(void) -{ - tu_memclr(_vendord_itf, sizeof(_vendord_itf)); - - for(uint8_t i=0; irx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); -#endif - } -} - -void vendord_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_itf->tx_ff); - } -} - -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - - uint8_t const * p_desc = tu_desc_next(desc_itf); - uint8_t const * desc_end = p_desc + max_len; - - // Find available interface - vendord_interface_t* p_vendor = NULL; - for(uint8_t i=0; iitf_num = desc_itf->bInterfaceNumber; - if (desc_itf->bNumEndpoints) - { - // skip non-endpoint descriptors - while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) - { - p_desc = tu_desc_next(p_desc); - } - - // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); - - p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - // Prepare for incoming data - if ( p_vendor->ep_out ) - { - _prep_out_transaction(p_vendor); - } - - if ( p_vendor->ep_in ) tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); - } - - return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf); -} - -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - uint8_t itf = 0; - vendord_interface_t* p_itf = _vendord_itf; - - for ( ; ; itf++, p_itf++) - { - if (itf >= TU_ARRAY_SIZE(_vendord_itf)) return false; - - if ( ( ep_addr == p_itf->ep_out ) || ( ep_addr == p_itf->ep_in ) ) break; - } - - if ( ep_addr == p_itf->ep_out ) - { - // Receive new data - tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, (uint16_t) xferred_bytes); - - // Invoked callback if any - if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); - - _prep_out_transaction(p_itf); - } - else if ( ep_addr == p_itf->ep_in ) - { - if (tud_vendor_tx_cb) tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes); - // Send complete, try to send more if possible - tud_vendor_n_write_flush(itf); - } - - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.h b/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.h deleted file mode 100644 index d239406b..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_device.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ - -#include "common/tusb_common.h" - -#ifndef CFG_TUD_VENDOR_EPSIZE -#define CFG_TUD_VENDOR_EPSIZE 64 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -//--------------------------------------------------------------------+ -bool tud_vendor_n_mounted (uint8_t itf); - -uint32_t tud_vendor_n_available (uint8_t itf); -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); -void tud_vendor_n_read_flush (uint8_t itf); - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -uint32_t tud_vendor_n_write_flush (uint8_t itf); -uint32_t tud_vendor_n_write_available (uint8_t itf); - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); - -// backward compatible -#define tud_vendor_n_flush(itf) tud_vendor_n_write_flush(itf) - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_vendor_mounted (void); -static inline uint32_t tud_vendor_available (void); -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (uint8_t* ui8); -static inline void tud_vendor_read_flush (void); -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_vendor_write_str (char const* str); -static inline uint32_t tud_vendor_write_available (void); -static inline uint32_t tud_vendor_write_flush (void); - -// backward compatible -#define tud_vendor_flush() tud_vendor_write_flush() - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); -// Invoked when last rx transfer finished -TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str) -{ - return tud_vendor_n_write(itf, str, strlen(str)); -} - -static inline bool tud_vendor_mounted (void) -{ - return tud_vendor_n_mounted(0); -} - -static inline uint32_t tud_vendor_available (void) -{ - return tud_vendor_n_available(0); -} - -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) -{ - return tud_vendor_n_read(0, buffer, bufsize); -} - -static inline bool tud_vendor_peek (uint8_t* ui8) -{ - return tud_vendor_n_peek(0, ui8); -} - -static inline void tud_vendor_read_flush(void) -{ - tud_vendor_n_read_flush(0); -} - -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) -{ - return tud_vendor_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_vendor_write_flush (void) -{ - return tud_vendor_n_write_flush(0); -} - -static inline uint32_t tud_vendor_write_str (char const* str) -{ - return tud_vendor_n_write_str(0, str); -} - -static inline uint32_t tud_vendor_write_available (void) -{ - return tud_vendor_n_write_available(0); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_DEVICE_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.c b/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.c deleted file mode 100644 index e66c5007..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_VENDOR) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "host/usbh.h" -#include "vendor_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; - -static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) - { - return TUSB_ERROR_DEVICE_NOT_READY; - } - - TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); - - return TUSB_ERROR_NONE; -} -//--------------------------------------------------------------------+ -// APPLICATION API (need to check parameters) -//--------------------------------------------------------------------+ -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS API -//--------------------------------------------------------------------+ -void cush_init(void) -{ - tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); -} - -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) -{ - // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; - p_desc = tu_desc_next(p_desc); - - //------------- Bulk Endpoints Descriptor -------------// - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); - - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? - &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); - TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - - p_desc = tu_desc_next(p_desc); - } - - (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return TUSB_ERROR_NONE; -} - -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) -{ - -} - -void cush_close(uint8_t dev_addr) -{ - tusb_error_t err1, err2; - custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; - - // TODO re-consider to check pipe valid before calling pipe_close - if( pipehandle_is_valid( p_interface->pipe_in ) ) - { - err1 = hcd_pipe_close( p_interface->pipe_in ); - } - - if ( pipehandle_is_valid( p_interface->pipe_out ) ) - { - err2 = hcd_pipe_close( p_interface->pipe_out ); - } - - tu_memclr(p_interface, sizeof(custom_interface_info_t)); - - TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.h b/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.h deleted file mode 100644 index acfebe7a..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/vendor/vendor_host.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct { - pipe_handle_t pipe_in; - pipe_handle_t pipe_out; -}custom_interface_info_t; - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) -{ - (void) vendor_id; // TODO check this later - (void) product_id; -// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0; - return false; -} - -bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); -bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cush_init(void); -bool cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); -void cush_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_HOST_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/class/video/video.h b/test-devices/composite-stm32/lib/tinyusb/class/video/video.h deleted file mode 100644 index c0088c4f..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/video/video.h +++ /dev/null @@ -1,559 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_H_ -#define TUSB_VIDEO_H_ - -#include "common/tusb_common.h" - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, - VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) - VIDEO_COLOR_PRIMARIES_BT470_2M, - VIDEO_COLOR_PRIMARIES_BT470_2BG, - VIDEO_COLOR_PRIMARIES_SMPTE170M, - VIDEO_COLOR_PRIMARIES_SMPTE240M, -} video_color_primaries_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, - VIDEO_COLOR_XFER_CH_BT709, // default - VIDEO_COLOR_XFER_CH_BT470_2M, - VIDEO_COLOR_XFER_CH_BT470_2BG, - VIDEO_COLOR_XFER_CH_SMPTE170M, - VIDEO_COLOR_XFER_CH_SMPTE240M, - VIDEO_COLOR_XFER_CH_LINEAR, - VIDEO_COLOR_XFER_CH_SRGB, -} video_color_transfer_characteristics_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_COEF_UNDEFINED = 0x00, - VIDEO_COLOR_COEF_BT709, - VIDEO_COLOR_COEF_FCC, - VIDEO_COLOR_COEF_BT470_2BG, - VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default - VIDEO_COLOR_COEF_SMPTE240M, -} video_color_matrix_coefficients_t; - -/* 4.2.1.2 Request Error Code Control */ -typedef enum { - VIDEO_ERROR_NONE = 0, /* The request succeeded. */ - VIDEO_ERROR_NOT_READY, - VIDEO_ERROR_WRONG_STATE, - VIDEO_ERROR_POWER, - VIDEO_ERROR_OUT_OF_RANGE, - VIDEO_ERROR_INVALID_UNIT, - VIDEO_ERROR_INVALID_CONTROL, - VIDEO_ERROR_INVALID_REQUEST, - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, - VIDEO_ERROR_UNKNOWN = 0xFF, -} video_error_code_t; - -/* A.2 Interface Subclass */ -typedef enum { - VIDEO_SUBCLASS_UNDEFINED = 0x00, - VIDEO_SUBCLASS_CONTROL, - VIDEO_SUBCLASS_STREAMING, - VIDEO_SUBCLASS_INTERFACE_COLLECTION, -} video_subclass_type_t; - -/* A.3 Interface Protocol */ -typedef enum { - VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, - VIDEO_ITF_PROTOCOL_15, -} video_interface_protocol_code_t; - -/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VC_UNDEFINED = 0x00, - VIDEO_CS_ITF_VC_HEADER, - VIDEO_CS_ITF_VC_INPUT_TERMINAL, - VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - VIDEO_CS_ITF_VC_SELECTOR_UNIT, - VIDEO_CS_ITF_VC_PROCESSING_UNIT, - VIDEO_CS_ITF_VC_EXTENSION_UNIT, - VIDEO_CS_ITF_VC_ENCODING_UNIT, - VIDEO_CS_ITF_VC_MAX, -} video_cs_vc_interface_subtype_t; - -/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VS_UNDEFINED = 0x00, - VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, - VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, - VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, - VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, - VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, - VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, - VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, - VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, - VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, - VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, - VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, - VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, - VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, - VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, - VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, - VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, - VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, - VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, - VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, -} video_cs_vs_interface_subtype_t; - -/* A.7. Class-Specific Endpoint Descriptor Subtypes */ -typedef enum { - VIDEO_CS_EP_UNDEFINED = 0x00, - VIDEO_CS_EP_GENERAL, - VIDEO_CS_EP_ENDPOINT, - VIDEO_CS_EP_INTERRUPT -} video_cs_ep_subtype_t; - -/* A.8 Class-Specific Request Codes */ -typedef enum { - VIDEO_REQUEST_UNDEFINED = 0x00, - VIDEO_REQUEST_SET_CUR = 0x01, - VIDEO_REQUEST_SET_CUR_ALL = 0x11, - VIDEO_REQUEST_GET_CUR = 0x81, - VIDEO_REQUEST_GET_MIN = 0x82, - VIDEO_REQUEST_GET_MAX = 0x83, - VIDEO_REQUEST_GET_RES = 0x84, - VIDEO_REQUEST_GET_LEN = 0x85, - VIDEO_REQUEST_GET_INFO = 0x86, - VIDEO_REQUEST_GET_DEF = 0x87, - VIDEO_REQUEST_GET_CUR_ALL = 0x91, - VIDEO_REQUEST_GET_MIN_ALL = 0x92, - VIDEO_REQUEST_GET_MAX_ALL = 0x93, - VIDEO_REQUEST_GET_RES_ALL = 0x94, - VIDEO_REQUEST_GET_DEF_ALL = 0x97 -} video_control_request_t; - -/* A.9.1 VideoControl Interface Control Selectors */ -typedef enum { - VIDEO_VC_CTL_UNDEFINED = 0x00, - VIDEO_VC_CTL_VIDEO_POWER_MODE, - VIDEO_VC_CTL_REQUEST_ERROR_CODE, -} video_interface_control_selector_t; - -/* A.9.8 VideoStreaming Interface Control Selectors */ -typedef enum { - VIDEO_VS_CTL_UNDEFINED = 0x00, - VIDEO_VS_CTL_PROBE, - VIDEO_VS_CTL_COMMIT, - VIDEO_VS_CTL_STILL_PROBE, - VIDEO_VS_CTL_STILL_COMMIT, - VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, - VIDEO_VS_CTL_STREAM_ERROR_CODE, - VIDEO_VS_CTL_GENERATE_KEY_FRAME, - VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, - VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, -} video_interface_streaming_selector_t; - -/* B. Terminal Types */ -typedef enum { - // Terminal - VIDEO_TT_VENDOR_SPECIFIC = 0x0100, - VIDEO_TT_STREAMING = 0x0101, - - // Input - VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, - VIDEO_ITT_CAMERA = 0x0201, - VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, - - // Output - VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, - VIDEO_OTT_DISPLAY = 0x0301, - VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, - - // External - VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, - VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, - VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, - VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, -} video_terminal_type_t; - -//--------------------------------------------------------------------+ -// Descriptors -//--------------------------------------------------------------------+ - -/* 2.3.4.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; - -/* 2.4.3.3 */ -typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; - -/* 3.9.2.1 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; - -/* 3.9.2.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - union { - struct { - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; - } input; - struct { - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; - } output; - }; -} tusb_desc_cs_video_stm_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t bmFlags; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_mjpeg_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint8_t bFormatType; -} tusb_desc_cs_video_fmt_dv_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; - uint8_t bVaribaleSize; -} tusb_desc_cs_video_fmt_frame_based_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwBytesPerLine; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_frame_based_t; - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ - -/* 4.3.1.1 */ -typedef struct TU_ATTR_PACKED { - union { - uint8_t bmHint; - struct TU_ATTR_PACKED { - uint16_t dwFrameInterval: 1; - uint16_t wKeyFrameRatel : 1; - uint16_t wPFrameRate : 1; - uint16_t wCompQuality : 1; - uint16_t wCompWindowSize: 1; - uint16_t : 0; - } Hint; - }; - uint8_t bFormatIndex; - uint8_t bFrameIndex; - uint32_t dwFrameInterval; - uint16_t wKeyFrameRate; - uint16_t wPFrameRate; - uint16_t wCompQuality; - uint16_t wCompWindowSize; - uint16_t wDelay; - uint32_t dwMaxVideoFrameSize; - uint32_t dwMaxPayloadTransferSize; - uint32_t dwClockFrequency; - union { - uint8_t bmFramingInfo; - struct TU_ATTR_PACKED { - uint8_t FrameID : 1; - uint8_t EndOfFrame: 1; - uint8_t EndOfSlice: 1; - uint8_t : 0; - } FramingInfo; - }; - uint8_t bPreferedVersion; - uint8_t bMinVersion; - uint8_t bMaxVersion; - uint8_t bUsage; - uint8_t bBitDepthLuma; - uint8_t bmSettings; - uint8_t bMaxNumberOfRefFramesPlus1; - uint16_t bmRateControlModes; - uint64_t bmLayoutPerStream; -} video_probe_and_commit_control_t; - -TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); - -#define TUD_VIDEO_DESC_IAD_LEN 8 -#define TUD_VIDEO_DESC_STD_VC_LEN 9 -#define TUD_VIDEO_DESC_CS_VC_LEN 12 -#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 -#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 -#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 -#define TUD_VIDEO_DESC_STD_VS_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 -#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 -#define TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN 11 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 - -/* 2.2 compression formats */ -#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 - -#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ - _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ - VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx - -#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ - TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ - _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.7.2 */ -#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ - TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ - U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ - U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ - -/* 3.7.2.1 */ -#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ - TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _stridx - -/* 3.7.2.2 */ -#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ - TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx - -/* 3.7.2.3 */ -#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ - U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ - TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) - -/* 3.9.1 */ -#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ - TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ - _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.9.2.1 */ -#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ - TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.2 */ -#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ - TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Uncompressed 3.1.1 */ -#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 - -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ - _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ - _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ - _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp - -/* Uncompressed 3.1.2 Table 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Uncompressed 3.1.2 Table 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Motion-JPEG 3.1.1 Table 3-1 */ -#define TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(_fmtidx, _numfrmdesc, _fixed_sz, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_MJPEG, \ - _fmtidx, _numfrmdesc, _fixed_sz, _frmidx, _asrx, _asry, _interlace, _cp - -/* Motion-JPEG 3.1.1 Table 3-2 and 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_MJPEG, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Motion-JPEG 3.1.1 Table 3-2 and 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_VS_INTERFACE_FRAME_MJPEG, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.6 */ -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ - TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ - _color, _trns, _mat - -/* 3.10.1.1 */ -#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS),\ - U16_TO_U8S_LE(_epsize), _ep_interval - -/* 3.10.1.2 */ -#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.c b/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.c deleted file mode 100644 index d6e98602..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.c +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "video_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; -} tusb_desc_vc_itf_t; - -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_vs_itf_t; - -typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_video_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bEntityId; -} tusb_desc_cs_video_entity_itf_t; - -typedef union { - struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - }; - tusb_desc_cs_video_fmt_uncompressed_t uncompressed; - tusb_desc_cs_video_fmt_mjpeg_t mjpeg; - tusb_desc_cs_video_fmt_frame_based_t frame_based; -} tusb_desc_cs_video_fmt_t; - -typedef union { - struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - }; - tusb_desc_cs_video_frm_uncompressed_t uncompressed; - tusb_desc_cs_video_frm_mjpeg_t mjpeg; - tusb_desc_cs_video_frm_frame_based_t frame_based; -} tusb_desc_cs_video_frm_t; - -/* video streaming interface */ -typedef struct TU_ATTR_PACKED { - uint8_t index_vc; /* index of bound video control interface */ - uint8_t index_vs; /* index from the video control interface */ - struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ - uint16_t end; /* Offset of the end of video streaming interface descriptor */ - uint16_t cur; /* Offset of the current settings */ - uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ - } desc; - uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ - uint32_t bufsize; /* frame buffer size */ - uint32_t offset; /* offset for the next payload transfer */ - uint32_t max_payload_transfer_size; - uint8_t error_code;/* error code */ - /*------------- From this point, data is not cleared by bus reset -------------*/ - CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ -} videod_streaming_interface_t; - -/* video control interface */ -typedef struct TU_ATTR_PACKED { - uint8_t const *beg; /* The head of the first video control interface descriptor */ - uint16_t len; /* Byte length of the descriptors */ - uint16_t cur; /* offset for current video control interface */ - uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ - uint8_t error_code; /* error code */ - uint8_t power_mode; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ - -} videod_interface_t; - -#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION tu_static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; -CFG_TUSB_MEM_SECTION tu_static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; - -tu_static uint8_t const _cap_get = 0x1u; /* support for GET */ -tu_static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ - -/** Get interface number from the interface descriptor - * - * @param[in] desc interface descriptor - * - * @return bInterfaceNumber */ -static inline uint8_t _desc_itfnum(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get endpoint address from the endpoint descriptor - * - * @param[in] desc endpoint descriptor - * - * @return bEndpointAddress */ -static inline uint8_t _desc_ep_addr(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get instance of streaming interface - * - * @param[in] ctl_idx instance number of video control - * @param[in] stm_idx index number of streaming interface - * - * @return instance */ -static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; - videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; - return stm; -} - -static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) -{ - return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); -} - -static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) -{ - if (!self->desc.cur) return NULL; - uint8_t const *desc = _videod_itf[self->index_vc].beg; - return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); -} - -/** Find the first descriptor of a given type - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) -{ - void const *cur = beg; - while ((cur < end) && (desc_type != tu_desc_type(cur))) { - cur = tu_desc_next(cur); - } - return cur; -} - -/** Find the first descriptor specified by the arguments - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type - * @param[in] element_0 The target element following the desc_type - * @param[in] element_1 The target element following the element_0 - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_3(void const *beg, void const *end, - uint_fast8_t desc_type, - uint_fast8_t element_0, - uint_fast8_t element_1) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { - uint8_t const *p = (uint8_t const *)cur; - if ((p[2] == element_0) && (p[3] == element_1)) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the next interface descriptor which has another interface number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _next_desc_itf(void const *beg, void const *end) -{ - void const *cur = beg; - uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; - while ((cur < end) && - (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { - cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); - } - return cur; -} - -/** Find the first interface descriptor with the specified interface number and alternate setting number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] itfnum The target interface number. - * @param[in] altnum The target alternate setting number. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static inline uint8_t const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) -{ - return (uint8_t const*) _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); -} - -/** Find the first endpoint descriptor belonging to the current interface descriptor. - * - * The search range is from `beg` to `end` or the next interface descriptor. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for endpoint descriptor. - * @retval end did not found endpoint descriptor */ -static void const* _find_desc_ep(void const *beg, void const *end) -{ - for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { - uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; - } - return end; -} - -/** Return the end of the video control descriptor. */ -static inline void const* _end_of_control_descriptor(void const *desc) -{ - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)desc; - return ((uint8_t const*) desc) + vc->std.bLength + tu_le16toh(vc->ctl.wTotalLength); -} - -/** Find the first entity descriptor with the entity ID - * specified by the argument belonging to the current video control descriptor. - * - * @param[in] desc The video control interface descriptor. - * @param[in] entityid The target entity id. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) -{ - void const *end = _end_of_control_descriptor(desc); - for (void const *cur = desc; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; - if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype - && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) - && itf->bEntityId == entityid) { - return itf; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the end of the video streaming descriptor. */ -static inline void const* _end_of_streaming_descriptor(void const *desc) -{ - tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; - return ((uint8_t const*) desc) + vs->std.bLength + tu_le16toh(vs->stm.wTotalLength); -} - -/** Find the first format descriptor with the specified format number. */ -static inline void const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - uint8_t const *p = (uint8_t const *)cur; - uint_fast8_t fmt = p[2]; - if ((fmt == VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED || - fmt == VIDEO_CS_ITF_VS_FORMAT_MJPEG || - fmt == VIDEO_CS_ITF_VS_FORMAT_DV || - fmt == VIDEO_CS_ITF_VS_FRAME_FRAME_BASED) && - fmtnum == p[3]) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Find the first frame descriptor with the specified format number. */ -static inline void const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - uint8_t const *p = (uint8_t const *)cur; - uint_fast8_t frm = p[2]; - if ((frm == VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED || - frm == VIDEO_CS_ITF_VS_FRAME_MJPEG || - frm == VIDEO_CS_ITF_VS_FRAME_FRAME_BASED) && - frmnum == p[3]) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Set uniquely determined values to variables that have not been set - * - * @param[in,out] param Target */ -static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, - video_probe_and_commit_control_t *param) -{ - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - uint_fast8_t fmtnum = param->bFormatIndex; - TU_ASSERT(vs && fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ - fmtnum = 1; - param->bFormatIndex = 1; - } - - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - TU_ASSERT(fmt != end); - - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - param->wCompQuality = 1; /* 1 to 10000 */ - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - break; - default: return false; - } - - uint_fast8_t frmnum = param->bFrameIndex; - TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; - frmnum = 1; - param->bFrameIndex = 1; - } - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - TU_ASSERT(frm != end); - - /* Set the parameters determined by the frame */ - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */ - break; - default: break; - } - param->dwMaxVideoFrameSize = frame_size; - } - - uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { - if ((1 < frm->uncompressed.bFrameIntervalType) || - ((0 == frm->uncompressed.bFrameIntervalType) && - (frm->uncompressed.dwFrameInterval[1] != frm->uncompressed.dwFrameInterval[0]))) { - return true; - } - interval = frm->uncompressed.dwFrameInterval[0]; - param->dwFrameInterval = interval; - } - uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); - uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) - payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; - param->dwMaxPayloadTransferSize = payload_size; - return true; -} - -/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host - * - * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF - * @param[in,out] param Target - */ -static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, - video_probe_and_commit_control_t *param) -{ - uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { - switch (request) { - case VIDEO_REQUEST_GET_MAX: - if (_get_desc_vs(stm)) - param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; - break; - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_DEF: - param->bFormatIndex = 1; - break; - default: return false; - } - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - return true; - } - - uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - TU_ASSERT(vs); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - switch (request) { - case VIDEO_REQUEST_GET_MAX: - frmnum = fmt->bNumFrameDescriptors; - break; - case VIDEO_REQUEST_GET_MIN: - frmnum = 1; - break; - case VIDEO_REQUEST_GET_DEF: - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frmnum = fmt->uncompressed.bDefaultFrameIndex; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frmnum = fmt->mjpeg.bDefaultFrameIndex; - break; - default: return false; - } - break; - default: return false; - } - param->bFrameIndex = (uint8_t)frmnum; - /* Set the parameters determined by the frame */ - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - uint_fast32_t frame_size; - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */ - break; - default: return false; - } - param->dwMaxVideoFrameSize = frame_size; - return true; - } - - if (!param->dwFrameInterval) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - TU_ASSERT(vs); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - - uint_fast32_t interval, interval_ms; - switch (request) { - case VIDEO_REQUEST_GET_MAX: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1]; - min_interval = frm->uncompressed.dwFrameInterval[0]; - interval = max_interval; - interval_ms = min_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_MIN: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1]; - min_interval = frm->uncompressed.dwFrameInterval[0]; - interval = min_interval; - interval_ms = max_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_DEF: - interval = frm->uncompressed.dwDefaultFrameInterval; - interval_ms = interval / 10000; - break; - case VIDEO_REQUEST_GET_RES: - { - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - if (num_intervals) { - interval = 0; - } else { - interval = frm->uncompressed.dwFrameInterval[2]; - interval_ms = interval / 10000; - } - } - break; - default: return false; - } - param->dwFrameInterval = interval; - if (!interval) { - param->dwMaxPayloadTransferSize = 0; - } else { - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - uint_fast32_t payload_size; - if (!interval_ms) { - payload_size = frame_size + 2; - } else { - payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - } - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) - payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; - param->dwMaxPayloadTransferSize = payload_size; - } - return true; - } - return true; -} - -/** Close current video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) -{ - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - - /* The next descriptor after the class-specific VC interface header descriptor. */ - void const *cur = (uint8_t const*)vc + vc->std.bLength + vc->ctl.bLength; - - /* The end of the video control interface descriptor. */ - void const *end = _end_of_control_descriptor(vc); - if (vc->std.bNumEndpoints) { - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - usbd_edpt_close(rhport, notif->bEndpointAddress); - } - self->cur = 0; - return true; -} - -/** Set the alternate setting to own video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) -{ - TU_LOG2(" open VC %d\n", altnum); - uint8_t const *beg = self->beg; - uint8_t const *end = beg + self->len; - - /* The first descriptor is a video control interface descriptor. */ - uint8_t const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_LOG2(" cur %d\n", cur - beg); - TU_VERIFY(cur < end); - - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; - TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); - /* Support for up to 2 streaming interfaces only. */ - TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); - - /* Update to point the end of the video control interface descriptor. */ - end = _end_of_control_descriptor(cur); - - /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ - cur += vc->std.bLength + vc->ctl.bLength; - TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); - /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { - /* Support for 1 endpoint only. */ - TU_VERIFY(1 == vc->std.bNumEndpoints); - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_VERIFY(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - /* Open the notification endpoint */ - TU_ASSERT(usbd_edpt_open(rhport, notif)); - } - self->cur = (uint16_t) ((uint8_t const*)vc - beg); - return true; -} - -/** Set the alternate setting to own video streaming interface. - * - * @param[in,out] stm Streaming interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) -{ - uint_fast8_t i; - TU_LOG2(" reopen VS %d\n", altnum); - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - - /* Close endpoints of previous settings. */ - for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) break; - uint8_t ep_adr = _desc_ep_addr(desc + ofs_ep); - usbd_edpt_close(rhport, ep_adr); - stm->desc.ep[i] = 0; - TU_LOG2(" close EP%02x\n", ep_adr); - } - - /* clear transfer management information */ - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - - /* Find a alternate interface */ - uint8_t const *beg = desc + stm->desc.beg; - uint8_t const *end = desc + stm->desc.end; - uint8_t const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_VERIFY(cur < end); - - uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; - TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); - stm->desc.cur = (uint16_t) (cur - desc); /* Save the offset of the new settings */ - if (!altnum) { - /* initialize streaming settings */ - stm->max_payload_transfer_size = 0; - video_probe_and_commit_control_t *param = - (video_probe_and_commit_control_t *)&stm->ep_buf; - tu_memclr(param, sizeof(*param)); - TU_LOG2(" done 0\n"); - return _update_streaming_parameters(stm, param); - } - /* Open endpoints of the new settings. */ - for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { - cur = _find_desc_ep(cur, end); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; - if (!stm->max_payload_transfer_size) { - video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; - uint_fast32_t max_size = param->dwMaxPayloadTransferSize; - if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && - (tu_edpt_packet_size(ep) < max_size)) - { - /* FS must be less than or equal to max packet size */ - return false; - } - /* Set the negotiated value */ - stm->max_payload_transfer_size = max_size; - } - TU_ASSERT(usbd_edpt_open(rhport, ep)); - stm->desc.ep[i] = (uint16_t) (cur - desc); - TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); - } - /* initialize payload header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->bHeaderLength = sizeof(*hdr); - hdr->bmHeaderInfo = 0; - - TU_LOG2(" done\n"); - return true; -} - -/** Prepare the next packet payload. */ -static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) -{ - uint_fast16_t remaining = stm->bufsize - stm->offset; - uint_fast16_t hdr_len = stm->ep_buf[0]; - uint_fast16_t pkt_len = stm->max_payload_transfer_size; - if (hdr_len + remaining < pkt_len) { - pkt_len = hdr_len + remaining; - } - uint_fast16_t data_len = pkt_len - hdr_len; - memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); - stm->offset += data_len; - remaining -= data_len; - if (!remaining) { - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->EndOfFrame = 1; - } - return hdr_len + data_len; -} - -/** Handle a standard request to the video control interface. */ -static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); - TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); - - uint8_t alt_num = vc->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - videod_interface_t *self = &_videod_itf[ctl_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VC_CTL_VIDEO_POWER_MODE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VC_CTL_REQUEST_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - uint_fast8_t entity_id; - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); - - case TUSB_REQ_TYPE_CLASS: - entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { - return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); - } else { - TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); - return VIDEO_ERROR_NONE; - } - - default: - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); - TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); - uint8_t alt_num = vs->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - (void)rhport; - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VS_CTL_STREAM_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - /* TODO */ - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_PROBE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), - VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_MAX: - case VIDEO_REQUEST_GET_RES: - case VIDEO_REQUEST_GET_DEF: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - video_probe_and_commit_control_t tmp; - tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; - TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t)&_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_COMMIT: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - if (tud_video_commit_cb) { - return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); - } - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_STILL_PROBE: - case VIDEO_VS_CTL_STILL_COMMIT: - case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: - case VIDEO_VS_CTL_GENERATE_KEY_FRAME: - case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: - case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: - /* TODO */ - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_stm_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_stm_std_req(rhport, stage, request, stm_idx); - - case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; - return handle_video_stm_cs_req(rhport, stage, request, stm_idx); - - default: return VIDEO_ERROR_INVALID_REQUEST; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; - return false; -} - -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - return true; -} - -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - - /* Find EP address */ - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - uint8_t ep_addr = 0; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; - ep_addr = _desc_ep_addr(desc + ofs_ep); - break; - } - if (!ep_addr) return false; - - TU_VERIFY( usbd_edpt_claim(0, ep_addr) ); - /* update the packet header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->FrameID ^= 1; - hdr->EndOfFrame = 0; - /* update the packet data */ - stm->buffer = (uint8_t*)buffer; - stm->bufsize = bufsize; - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void videod_init(void) -{ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -void videod_reset(uint8_t rhport) -{ - (void) rhport; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && - (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && - (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); - - /* Find available interface */ - videod_interface_t *self = NULL; - uint8_t ctl_idx; - for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; - self = &_videod_itf[ctl_idx]; - break; - } - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); - - uint8_t const *end = (uint8_t const*)itf_desc + max_len; - self->beg = (uint8_t const*) itf_desc; - self->len = max_len; - - /*------------- Video Control Interface -------------*/ - TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - uint_fast8_t bInCollection = vc->ctl.bInCollection; - - /* Find the end of the video interface descriptor */ - void const *cur = _next_desc_itf(itf_desc, end); - for (uint8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { - videod_streaming_interface_t *stm = NULL; - /* find free streaming interface handle */ - for (uint8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; - stm = &_videod_streaming_itf[i]; - self->stm[stm_idx] = i; - break; - } - TU_ASSERT(stm, 0); - stm->index_vc = ctl_idx; - stm->index_vs = stm_idx; - stm->desc.beg = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - cur = _next_desc_itf(cur, end); - stm->desc.end = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - } - self->len = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - return (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - int err; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - uint_fast8_t itfnum = tu_u16_low(request->wIndex); - - /* Identify which control interface to use */ - uint_fast8_t itf; - for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { - void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; - } - - if (itf < CFG_TUD_VIDEO) { - err = handle_video_ctl_req(rhport, stage, request, itf); - _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - - /* Identify which streaming interface to use */ - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; - } - - if (itf < CFG_TUD_VIDEO_STREAMING) { - err = handle_video_stm_req(rhport, stage, request, itf); - _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - return false; -} - -bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; (void)xferred_bytes; - - /* find streaming handle */ - uint_fast8_t itf; - videod_interface_t *ctl; - videod_streaming_interface_t *stm; - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - stm = &_videod_streaming_itf[itf]; - uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; - ctl = &_videod_itf[stm->index_vc]; - uint8_t const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; - } - - TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); - if (stm->offset < stm->bufsize) { - /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0); - } else { - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - if (tud_video_frame_xfer_complete_cb) { - tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); - } - } - return true; -} - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.h b/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.h deleted file mode 100644 index ee2fcb9d..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/class/video/video_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_DEVICE_H_ -#define TUSB_VIDEO_DEVICE_H_ - -#include "common/tusb_common.h" -#include "video.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_VIDEO > 1 -//--------------------------------------------------------------------+ - -/** Return true if streaming - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -/** Transfer a frame - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. - * @param[in] bufsize Byte size of the frame buffer */ -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); - -/*------------- Optional callbacks -------------*/ -/** Invoked when compeletion of a frame transfer - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -/** Invoked when SET_POWER_MODE request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); - -/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] parameters Video streaming parameters - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void videod_init (void); -void videod_reset (uint8_t rhport); -uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_common.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_common.h index 957491aa..0d4082c0 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_common.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_common.h @@ -37,6 +37,7 @@ #define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) #define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low))) #define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) @@ -53,6 +54,8 @@ #define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) #define TU_BIT(n) (1UL << (n)) + +// Generate a mask with bit from high (31) to low (0) set, e.g TU_GENMASK(3, 0) = 0b1111 #define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) //--------------------------------------------------------------------+ @@ -62,6 +65,7 @@ // Standard Headers #include #include +#include #include #include #include @@ -73,8 +77,6 @@ #include "tusb_types.h" #include "tusb_debug.h" -#include "tusb_timeout.h" // TODO remove - //--------------------------------------------------------------------+ // Optional API implemented by application if needed // TODO move to a more ovious place/file @@ -99,10 +101,9 @@ TU_ATTR_WEAK extern void* tusb_app_phys_to_virt(void *phys_addr); #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) // This is a backport of memset_s from c11 -TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) -{ +TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) { // TODO may check if desst and src is not NULL - if (count > destsz) { + if ( count > destsz ) { return -1; } memset(dest, ch, count); @@ -110,10 +111,9 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, i } // This is a backport of memcpy_s from c11 -TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void * src, size_t count ) -{ +TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) { // TODO may check if desst and src is not NULL - if (count > destsz) { + if ( count > destsz ) { return -1; } memcpy(dest, src, count); @@ -122,13 +122,11 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) { return (uint16_t) ((((uint16_t) high) << 8) | low); } @@ -159,16 +157,20 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } //------------- Align -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) { return value & ((uint32_t) ~(alignment-1)); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4 (uint32_t value) { return (value & 0xFFFFFFFCUL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align8 (uint32_t value) { return (value & 0xFFFFFFF8UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned32(uint32_t value) { return (value & 0x1FUL) == 0; } +TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { return (value & 0x3FUL) == 0; } + //------------- Mathematics -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } @@ -260,11 +262,21 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_ #else // MCU that could access unaligned memory natively -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void *mem) { + return *((uint32_t const *) mem); +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) { + return *((uint16_t const *) mem); +} -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void *mem, uint32_t value) { + *((uint32_t *) mem) = value; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_t value) { + *((uint16_t *) mem) = value; +} #endif diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_compiler.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_compiler.h index 5ab56e14..0d5570b1 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_compiler.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_compiler.h @@ -56,7 +56,7 @@ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert #elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, _TU_COUNTER_)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif @@ -128,7 +128,9 @@ #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #endif #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used @@ -205,7 +207,9 @@ #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #endif #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_debug.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_debug.h index 82f68204..2e9f1d9c 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_debug.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_debug.h @@ -43,9 +43,10 @@ #if CFG_TUSB_DEBUG // Enum to String for debugging purposes -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL extern char const* const tu_str_speed[]; extern char const* const tu_str_std_request[]; +extern char const* const tu_str_xfer_result[]; #endif void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); @@ -57,16 +58,15 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #define tu_printf printf #endif -static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) -{ +static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_ARR TU_LOG1_ARR - #define TU_LOG2_PTR TU_LOG1_PTR + #define TU_LOG2_BUF TU_LOG1_BUF #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX #endif @@ -94,30 +92,25 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #if CFG_TUSB_DEBUG >= 3 #define TU_LOG3 TU_LOG1 #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_ARR TU_LOG1_ARR - #define TU_LOG3_PTR TU_LOG1_PTR + #define TU_LOG3_BUF TU_LOG1_BUF #define TU_LOG3_INT TU_LOG1_INT #define TU_LOG3_HEX TU_LOG1_HEX #endif -typedef struct -{ +typedef struct { uint32_t key; const char* data; } tu_lookup_entry_t; -typedef struct -{ +typedef struct { uint16_t count; tu_lookup_entry_t const* items; } tu_lookup_table_t; -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { tu_static char not_found[11]; - for(uint16_t i=0; icount; i++) - { + for(uint16_t i=0; icount; i++) { if (p_table->items[i].key == key) return p_table->items[i].data; } @@ -132,7 +125,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG #define TU_LOG(n, ...) #define TU_LOG_MEM(n, ...) - #define TU_LOG_PTR(n, ...) + #define TU_LOG_BUF(n, ...) #define TU_LOG_INT(n, ...) #define TU_LOG_HEX(n, ...) #define TU_LOG_LOCATION() @@ -143,14 +136,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG0(...) #define TU_LOG0_MEM(...) -#define TU_LOG0_PTR(...) +#define TU_LOG0_BUF(...) #define TU_LOG0_INT(...) #define TU_LOG0_HEX(...) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) - #define TU_LOG1_PTR(...) + #define TU_LOG1_BUF(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) #endif @@ -158,7 +151,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) - #define TU_LOG2_PTR(...) + #define TU_LOG2_BUF(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) #endif @@ -166,7 +159,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG3 #define TU_LOG3(...) #define TU_LOG3_MEM(...) - #define TU_LOG3_PTR(...) + #define TU_LOG3_BUF(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) #endif diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.c b/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.c index a52c9226..76696396 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.c +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.c @@ -224,6 +224,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); } break; + default: break; } } @@ -539,7 +540,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance index f->wr_idx = advance_index(f->depth, wr_idx, n); - TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\n", f->wr_idx); + TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); } _ff_unlock(f->mutex_wr); diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.h index 2f60ec2f..2d9f5e66 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_fifo.h @@ -102,10 +102,8 @@ extern "C" { * | * ------------------------- * | R | 1 | 2 | W | 4 | 5 | - */ -typedef struct -{ +typedef struct { uint8_t* buffer ; // buffer pointer uint16_t depth ; // max items @@ -124,16 +122,14 @@ typedef struct } tu_fifo_t; -typedef struct -{ +typedef struct { uint16_t len_lin ; ///< linear length in item size uint16_t len_wrap ; ///< wrapped length in item size void * ptr_lin ; ///< linear part start pointer void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ -{ \ +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\ .buffer = _buffer, \ .depth = _depth, \ .item_size = sizeof(_type), \ @@ -144,23 +140,18 @@ typedef struct uint8_t _name##_buf[_depth*sizeof(_type)]; \ tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) - bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if OSAL_MUTEX_REQUIRED -TU_ATTR_ALWAYS_INLINE static inline -void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) -{ - f->mutex_wr = wr_mutex; - f->mutex_rd = rd_mutex; -} - + TU_ATTR_ALWAYS_INLINE static inline + void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) { + f->mutex_wr = wr_mutex; + f->mutex_rd = rd_mutex; + } #else - -#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) - + #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif bool tu_fifo_write (tu_fifo_t* f, void const * p_data); @@ -182,8 +173,7 @@ bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) -{ +uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; } @@ -198,7 +188,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - #ifdef __cplusplus } #endif diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_mcu.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_mcu.h index ba8976a8..5a567f2d 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_mcu.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_mcu.h @@ -34,10 +34,16 @@ //------------- Unaligned Memory Access -------------// -// ARMv7+ (M3-M7, M23-M33) can access unaligned memory -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) - #define TUP_ARCH_STRICT_ALIGN 0 +#ifdef __ARM_ARCH + // ARM Architecture set __ARM_FEATURE_UNALIGNED to 1 for mcu supports unaligned access + #if defined(__ARM_FEATURE_UNALIGNED) && __ARM_FEATURE_UNALIGNED == 1 + #define TUP_ARCH_STRICT_ALIGN 0 + #else + #define TUP_ARCH_STRICT_ALIGN 1 + #endif #else + // TODO default to strict align for others + // Should investigate other architecture such as risv, xtensa, mips for optimal setting #define TUP_ARCH_STRICT_ALIGN 1 #endif @@ -52,6 +58,7 @@ // NXP //--------------------------------------------------------------------+ #if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) @@ -59,33 +66,55 @@ #define TUP_USBIP_OHCI #define TUP_OHCI_RHPORTS 2 -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - // TODO USB0 has 6, USB1 has 4 - #define TUP_USBIP_CHIPIDEA_HS - #define TUP_USBIP_EHCI - - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 FS - #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC54) // TODO USB0 has 5, USB1 has 6 + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT) +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + // USB0 has 6 with HS PHY, USB1 has 4 only FS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_MCXN9) + // USB0 is chipidea FS + #define TUP_USBIP_CHIPIDEA_FS + #define TUP_USBIP_CHIPIDEA_FS_MCX + + // USB1 is chipidea HS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_MCXA15) + // USB0 is chipidea FS + #define TUP_USBIP_CHIPIDEA_FS + #define TUP_USBIP_CHIPIDEA_FS_MCX + + #define TUP_DCD_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 HS + #define TUP_RHPORT_HIGHSPEED 1 -#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32) +#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K) #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_KINETIS #define TUP_DCD_ENDPOINT_MAX 16 @@ -188,7 +217,22 @@ #define TUP_DCD_ENDPOINT_MAX 9 +#elif TU_CHECK_MCU(OPT_MCU_STM32H5) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_STM32G4) + // Device controller + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + + // TypeC controller + #define TUP_USBIP_TYPEC_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_TYPEC_RHPORTS_NUM 1 + +#elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 @@ -227,14 +271,21 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32U5) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 6 + + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY + #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ + defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 + #else + #define TUP_DCD_ENDPOINT_MAX 6 + #endif #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 - //--------------------------------------------------------------------+ // Sony //--------------------------------------------------------------------+ @@ -278,6 +329,9 @@ #define TUP_USBIP_DWC2 #define TUP_DCD_ENDPOINT_MAX 6 +#elif TU_CHECK_MCU(OPT_MCU_ESP32) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) + #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + //--------------------------------------------------------------------+ // Dialog //--------------------------------------------------------------------+ @@ -303,6 +357,7 @@ // Renesas //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N, OPT_MCU_RAXXX) + #define TUP_USBIP_RUSB2 #define TUP_DCD_ENDPOINT_MAX 10 //--------------------------------------------------------------------+ @@ -348,8 +403,24 @@ #elif TU_CHECK_MCU(OPT_MCU_CH32V307) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_CH32F20X) + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 +#endif + + +//--------------------------------------------------------------------+ +// External USB controller +//--------------------------------------------------------------------+ + +#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #endif #endif + //--------------------------------------------------------------------+ // Default Values //--------------------------------------------------------------------+ @@ -358,8 +429,8 @@ #define TUP_MCU_MULTIPLE_CORE 0 #endif -#ifndef TUP_DCD_ENDPOINT_MAX - #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" +#if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED +#warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 #endif @@ -373,4 +444,8 @@ #define TU_ATTR_FAST_FUNC #endif +#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) + #define TUP_DCD_EDPT_ISO_ALLOC +#endif + #endif diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_private.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_private.h index d5541856..373a5025 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_private.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_private.h @@ -60,7 +60,7 @@ typedef struct { tu_fifo_t ff; // mutex: read if ep rx, write if e tx - OSAL_MUTEX_DEF(ff_mutex); + OSAL_MUTEX_DEF(ff_mutexdef); }tu_edpt_stream_t; @@ -87,15 +87,17 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); // Endpoint Stream //--------------------------------------------------------------------+ -// Init an stream, should only be called once +// Init an endpoint stream bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize); +// Deinit an endpoint stream +bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); + // Open an stream for an endpoint // hwid is either device address (host mode) or rhport (device mode) TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) -{ +void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) { tu_fifo_clear(&s->ff); s->hwid = hwid; s->ep_addr = desc_ep->bEndpointAddress; @@ -103,16 +105,14 @@ void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t } TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_close(tu_edpt_stream_t* s) -{ +void tu_edpt_stream_close(tu_edpt_stream_t* s) { s->hwid = 0; s->ep_addr = 0; } // Clear fifo TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_clear(tu_edpt_stream_t* s) -{ +bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { return tu_fifo_clear(&s->ff); } @@ -131,8 +131,7 @@ bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferr // Get the number of bytes available for writing TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) { return (uint32_t) tu_fifo_remaining(&s->ff); } @@ -148,21 +147,26 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s); // Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) -{ +void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } +// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes +TU_ATTR_ALWAYS_INLINE static inline +void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) { + if (skip_offset < xferred_bytes) { + tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset)); + } +} + // Get the number of bytes available for reading TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) { return (uint32_t) tu_fifo_count(&s->ff); } TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) -{ +bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) { return tu_fifo_peek(&s->ff, ch); } diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_timeout.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_timeout.h deleted file mode 100644 index 533e67ab..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_timeout.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - -#ifndef _TUSB_TIMEOUT_H_ -#define _TUSB_TIMEOUT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}tu_timeout_t; - -#if 0 - -extern uint32_t tusb_hal_millis(void); - -static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool tu_timeout_expired(tu_timeout_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -// For used with periodic event to prevent drift -static inline void tu_timeout_reset(tu_timeout_t* tt) -{ - tt->start += tt->interval; -} - -static inline void tu_timeout_restart(tu_timeout_t* tt) -{ - tt->start = tusb_hal_millis(); -} - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_H_ */ - -/** @} */ diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_types.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_types.h index 39a2d456..b571f9b7 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_types.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_types.h @@ -24,12 +24,8 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usb_definitions - * \defgroup USBDef_Type USB Types - * @{ */ - -#ifndef _TUSB_TYPES_H_ -#define _TUSB_TYPES_H_ +#ifndef TUSB_TYPES_H_ +#define TUSB_TYPES_H_ #include #include @@ -44,43 +40,38 @@ *------------------------------------------------------------------*/ /// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ +typedef enum { TUSB_SPEED_FULL = 0, TUSB_SPEED_LOW = 1, TUSB_SPEED_HIGH = 2, TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; +} tusb_speed_t; /// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ +typedef enum { TUSB_XFER_CONTROL = 0 , TUSB_XFER_ISOCHRONOUS , TUSB_XFER_BULK , TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; +} tusb_xfer_type_t; -typedef enum -{ +typedef enum { TUSB_DIR_OUT = 0, TUSB_DIR_IN = 1, TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; +} tusb_dir_t; -enum -{ +enum { TUSB_EPSIZE_BULK_FS = 64, - TUSB_EPSIZE_BULK_HS= 512, + TUSB_EPSIZE_BULK_HS = 512, TUSB_EPSIZE_ISO_FS_MAX = 1023, TUSB_EPSIZE_ISO_HS_MAX = 1024, }; -/// Isochronous End Point Attributes -typedef enum -{ +/// Isochronous Endpoint Attributes +typedef enum { TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, @@ -88,11 +79,10 @@ typedef enum TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; +} tusb_iso_ep_attribute_t; /// USB Descriptor Types -typedef enum -{ +typedef enum { TUSB_DESC_DEVICE = 0x01, TUSB_DESC_CONFIGURATION = 0x02, TUSB_DESC_STRING = 0x03, @@ -119,10 +109,9 @@ typedef enum TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; +} tusb_desc_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_GET_STATUS = 0 , TUSB_REQ_CLEAR_FEATURE = 1 , TUSB_REQ_RESERVED = 2 , @@ -136,25 +125,22 @@ typedef enum TUSB_REQ_GET_INTERFACE = 10 , TUSB_REQ_SET_INTERFACE = 11 , TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; +} tusb_request_code_t; -typedef enum -{ +typedef enum { TUSB_REQ_FEATURE_EDPT_HALT = 0, TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; +} tusb_request_feature_selector_t; -typedef enum -{ +typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID } tusb_request_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_RCPT_DEVICE =0, TUSB_REQ_RCPT_INTERFACE, TUSB_REQ_RCPT_ENDPOINT, @@ -162,8 +148,7 @@ typedef enum } tusb_request_recipient_t; // https://www.usb.org/defined-class-codes -typedef enum -{ +typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , TUSB_CLASS_AUDIO = 1 , TUSB_CLASS_CDC = 2 , @@ -187,26 +172,23 @@ typedef enum TUSB_CLASS_MISC = 0xEF , TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; +} tusb_class_code_t; typedef enum { MISC_SUBCLASS_COMMON = 2 }misc_subclass_type_t; -typedef enum -{ +typedef enum { MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; +} misc_protocol_type_t; -typedef enum -{ +typedef enum { APP_SUBCLASS_USBTMC = 0x03, APP_SUBCLASS_DFU_RUNTIME = 0x01 } app_subclass_type_t; -typedef enum -{ +typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, @@ -223,37 +205,37 @@ typedef enum DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; +} device_capability_type_t; enum { - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), - TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = 1u << 5, + TUSB_DESC_CONFIG_ATT_SELF_POWERED = 1u << 6, }; #define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) -typedef enum -{ +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +typedef enum { XFER_RESULT_SUCCESS = 0, XFER_RESULT_FAILED, XFER_RESULT_STALLED, XFER_RESULT_TIMEOUT, XFER_RESULT_INVALID -}xfer_result_t; +} xfer_result_t; -enum // TODO remove -{ +// TODO remove +enum { DESC_OFFSET_LEN = 0, DESC_OFFSET_TYPE = 1 }; -enum -{ +enum { INTERFACE_INVALID_NUMBER = 0xff }; -typedef enum -{ +typedef enum { MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, @@ -265,16 +247,14 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; -enum -{ +enum { CONTROL_STAGE_IDLE, CONTROL_STAGE_SETUP, CONTROL_STAGE_DATA, CONTROL_STAGE_ACK }; -enum -{ +enum { TUSB_INDEX_INVALID_8 = 0xFFu }; @@ -287,15 +267,14 @@ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. - uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. + uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). - uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. - uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. + uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). + uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). @@ -311,8 +290,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this descriptor @@ -322,8 +300,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); /// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. @@ -338,8 +315,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); /// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type @@ -355,8 +331,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); /// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; // Size of this descriptor in bytes uint8_t bDescriptorType ; // ENDPOINT Descriptor Type @@ -376,8 +351,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); /// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type uint16_t wTotalLength ; ///< Total length of data returned @@ -390,8 +364,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_other_speed_t; /// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Device Qualifier Type uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) @@ -408,8 +381,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); /// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type @@ -423,17 +395,17 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct"); + // USB String Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; // USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType ; uint8_t bDevCapabilityType; @@ -442,9 +414,8 @@ typedef struct TU_ATTR_PACKED uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ +// USB WebUSB URL Descriptor +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bScheme; @@ -452,8 +423,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -474,10 +444,11 @@ typedef struct TU_ATTR_PACKED uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -/*------------------------------------------------------------------*/ -/* Types - *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. @@ -496,7 +467,6 @@ typedef struct TU_ATTR_PACKED{ TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END @@ -505,36 +475,25 @@ TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Get direction from Endpoint address -TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; } // Get Endpoint number from address -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ - return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { + return tu_le16toh(desc_ep->wMaxPacketSize) & 0x7FF; } #if CFG_TUSB_DEBUG -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) -{ - tu_static const char *str[] = {"out", "in"}; - return str[dir]; -} - -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) { tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"}; return str[t]; } @@ -545,21 +504,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_ //--------------------------------------------------------------------+ // return next descriptor -TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { uint8_t const* desc8 = (uint8_t const*) desc; return desc8 + desc8[DESC_OFFSET_LEN]; } // get descriptor type -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } // get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; } @@ -576,6 +532,4 @@ uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t b } #endif -#endif /* _TUSB_TYPES_H_ */ - -/** @} */ +#endif // TUSB_TYPES_H_ diff --git a/test-devices/composite-stm32/lib/tinyusb/common/tusb_verify.h b/test-devices/composite-stm32/lib/tinyusb/common/tusb_verify.h index 12355e8b..0a9549c9 100644 --- a/test-devices/composite-stm32/lib/tinyusb/common/tusb_verify.h +++ b/test-devices/composite-stm32/lib/tinyusb/common/tusb_verify.h @@ -56,12 +56,8 @@ * #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond,ret) if(cond) return ret; * - * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} - * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} - * * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -79,15 +75,16 @@ #define _MESS_FAILED() do {} while (0) #endif -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \ + defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do \ { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#elif defined(__riscv) +#elif defined(__riscv) && !TUP_MCU_ESPRESSIF #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) #elif defined(_mips) @@ -97,40 +94,23 @@ #define TU_BREAKPOINT() do {} while (0) #endif -/*------------------------------------------------------------------*/ -/* Macro Generator - *------------------------------------------------------------------*/ - // Helper to implement optional parameter for TU_VERIFY Macro family #define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 - -/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ -#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ -{ \ - if ( !(_cond) ) { _handler; return _ret; } \ -} while(0) /*------------------------------------------------------------------*/ /* TU_VERIFY * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) -#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { return _ret; } \ + } while(0) -#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) - -/*------------------------------------------------------------------*/ -/* TU_VERIFY WITH HANDLER - * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) -#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) - -#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) +#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT @@ -138,19 +118,20 @@ * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) +#define TU_ASSERT_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \ + } while(0) + +#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false) +#define TU_ASSERT_2ARGS(_cond, _ret) TU_ASSERT_DEFINE(_cond, _ret) #ifndef TU_ASSERT -#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__) #endif -/*------------------------------------------------------------------*/ -/* ASSERT HDLR - *------------------------------------------------------------------*/ - #ifdef __cplusplus } #endif -#endif /* TUSB_VERIFY_H_ */ +#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/device/dcd.h b/test-devices/composite-stm32/lib/tinyusb/device/dcd.h index 00419ff0..d4f105aa 100644 --- a/test-devices/composite-stm32/lib/tinyusb/device/dcd.h +++ b/test-devices/composite-stm32/lib/tinyusb/device/dcd.h @@ -47,8 +47,7 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -typedef enum -{ +typedef enum { DCD_EVENT_INVALID = 0, DCD_EVENT_BUS_RESET, DCD_EVENT_UNPLUGGED, @@ -65,13 +64,11 @@ typedef enum DCD_EVENT_COUNT } dcd_eventid_t; -typedef struct TU_ATTR_ALIGNED(4) -{ +typedef struct TU_ATTR_ALIGNED(4) { uint8_t rhport; uint8_t event_id; - union - { + union { // BUS RESET struct { tusb_speed_t speed; @@ -102,12 +99,31 @@ typedef struct TU_ATTR_ALIGNED(4) //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); +//--------------------------------------------------------------------+ +// Memory API +//--------------------------------------------------------------------+ + +// clean/flush data cache: write cache -> memory. +// Required before an DMA TX transfer to make sure data is in memory +void dcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + +// invalidate data cache: mark cache as invalid, next read will read from memory +// Required BOTH before and after an DMA RX transfer +void dcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + +// clean and invalidate data cache +// Required before an DMA transfer where memory is both read/write by DMA +void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ // Initialize controller to device mode -void dcd_init (uint8_t rhport); +void dcd_init(uint8_t rhport); + +// Deinitialize controller, unset device mode. +bool dcd_deinit(uint8_t rhport); // Interrupt Handler void dcd_int_handler(uint8_t rhport); @@ -139,7 +155,7 @@ void dcd_sof_enable(uint8_t rhport, bool en); // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request); // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); @@ -168,11 +184,12 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); // Allocate packet buffer used by ISO endpoints -// Some MCU need manual packet buffer allocation, we allocation largest size to avoid clustering +// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); // Configure and enable an ISO endpoint according to descriptor -TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ @@ -181,23 +198,20 @@ TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t co extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); // helper to send bus signal event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = eid }; dcd_event_handler(&event, in_isr); } // helper to send bus reset event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; event.bus_reset.speed = speed; dcd_event_handler(&event, in_isr); } // helper to send setup received -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); @@ -205,8 +219,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport } // helper to send transfer complete event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; event.xfer_complete.ep_addr = ep_addr; @@ -216,8 +229,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport dcd_event_handler(&event, in_isr); } -static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SOF }; event.sof.frame_count = frame_count; dcd_event_handler(&event, in_isr); diff --git a/test-devices/composite-stm32/lib/tinyusb/device/usbd.c b/test-devices/composite-stm32/lib/tinyusb/device/usbd.c index cee56af6..e51aa0fc 100644 --- a/test-devices/composite-stm32/lib/tinyusb/device/usbd.c +++ b/test-devices/composite-stm32/lib/tinyusb/device/usbd.c @@ -38,13 +38,23 @@ //--------------------------------------------------------------------+ // USBD Configuration //--------------------------------------------------------------------+ - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -// Debug level of USBD -#define USBD_DBG 2 +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) { + (void) rhport; + return false; +} + +TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { + (void)rhport; + (void)eventid; + (void)in_isr; +} //--------------------------------------------------------------------+ // Device Data @@ -53,10 +63,8 @@ // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; -typedef struct -{ - struct TU_ATTR_PACKED - { +typedef struct { + struct TU_ATTR_PACKED { volatile uint8_t connected : 1; volatile uint8_t addressed : 1; volatile uint8_t suspended : 1; @@ -65,9 +73,9 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; - volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; + volatile uint8_t setup_count; uint8_t itf2drv[CFG_TUD_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each @@ -81,158 +89,169 @@ tu_static usbd_device_t _usbd_dev; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL #define DRIVER_NAME(_name) .name = _name, #else #define DRIVER_NAME(_name) #endif // Built-in class drivers -tu_static usbd_class_driver_t const _usbd_driver[] = -{ - #if CFG_TUD_CDC - { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MSC - { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_HID - { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_AUDIO - { - DRIVER_NAME("AUDIO") - .init = audiod_init, - .reset = audiod_reset, - .open = audiod_open, - .control_xfer_cb = audiod_control_xfer_cb, - .xfer_cb = audiod_xfer_cb, - .sof = audiod_sof_isr - }, - #endif - - #if CFG_TUD_VIDEO - { - DRIVER_NAME("VIDEO") - .init = videod_init, - .reset = videod_reset, - .open = videod_open, - .control_xfer_cb = videod_control_xfer_cb, - .xfer_cb = videod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MIDI - { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VENDOR - { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_xfer_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_USBTMC - { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_xfer_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU_RUNTIME - { - DRIVER_NAME("DFU-RUNTIME") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU - { - DRIVER_NAME("DFU") - .init = dfu_moded_init, - .reset = dfu_moded_reset, - .open = dfu_moded_open, - .control_xfer_cb = dfu_moded_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM - { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_xfer_cb, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - #endif - - #if CFG_TUD_BTH - { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_xfer_cb, - .xfer_cb = btd_xfer_cb, - .sof = NULL - }, - #endif +tu_static usbd_class_driver_t const _usbd_driver[] = { + #if CFG_TUD_CDC + { + DRIVER_NAME("CDC") + .init = cdcd_init, + .deinit = cdcd_deinit, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MSC + { + DRIVER_NAME("MSC") + .init = mscd_init, + .deinit = NULL, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_HID + { + DRIVER_NAME("HID") + .init = hidd_init, + .deinit = hidd_deinit, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") + .init = audiod_init, + .deinit = audiod_deinit, + .reset = audiod_reset, + .open = audiod_open, + .control_xfer_cb = audiod_control_xfer_cb, + .xfer_cb = audiod_xfer_cb, + .sof = audiod_sof_isr + }, + #endif + + #if CFG_TUD_VIDEO + { + DRIVER_NAME("VIDEO") + .init = videod_init, + .deinit = videod_deinit, + .reset = videod_reset, + .open = videod_open, + .control_xfer_cb = videod_control_xfer_cb, + .xfer_cb = videod_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MIDI + { + DRIVER_NAME("MIDI") + .init = midid_init, + .deinit = midid_deinit, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_VENDOR + { + DRIVER_NAME("VENDOR") + .init = vendord_init, + .deinit = vendord_deinit, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_xfer_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_USBTMC + { + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .deinit = usbtmcd_deinit, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU_RUNTIME + { + DRIVER_NAME("DFU-RUNTIME") + .init = dfu_rtd_init, + .deinit = dfu_rtd_deinit, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU + { + DRIVER_NAME("DFU") + .init = dfu_moded_init, + .deinit = dfu_moded_deinit, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM + { + DRIVER_NAME("NET") + .init = netd_init, + .deinit = netd_deinit, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_xfer_cb, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, + #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .deinit = btd_deinit, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_xfer_cb, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; @@ -241,25 +260,21 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; tu_static usbd_class_driver_t const * _app_driver = NULL; tu_static uint8_t _app_driver_count = 0; +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) + // virtually joins built-in and application drivers together. // Application is positioned first to allow overwriting built-in ones. -static inline usbd_class_driver_t const * get_driver(uint8_t drvid) -{ - // Application drivers - if ( usbd_app_driver_get_cb ) - { - if ( drvid < _app_driver_count ) return &_app_driver[drvid]; - drvid -= _app_driver_count; +TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { + usbd_class_driver_t const * driver = NULL; + if ( drvid < _app_driver_count ) { + // Application drivers + driver = &_app_driver[drvid]; + } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){ + driver = &_usbd_driver[drvid - _app_driver_count]; } - - // Built-in drivers - if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; - - return NULL; + return driver; } -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) - //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ @@ -280,6 +295,11 @@ tu_static osal_queue_t _usbd_q; #define _usbd_mutex NULL #endif +TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) { + TU_ASSERT(osal_queue_send(_usbd_q, event, in_isr)); + tud_event_hook_cb(event->rhport, event->event_id, in_isr); + return true; +} //--------------------------------------------------------------------+ // Prototypes @@ -298,29 +318,25 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 -tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = -{ - "Invalid" , - "Bus Reset" , - "Unplugged" , - "SOF" , - "Suspend" , - "Resume" , - "Setup Received" , - "Xfer Complete" , - "Func Call" +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL +tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { + "Invalid", + "Bus Reset", + "Unplugged", + "SOF", + "Suspend", + "Resume", + "Setup Received", + "Xfer Complete", + "Func Call" }; // for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) -{ - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver && driver->control_xfer_cb == callback ) - { - TU_LOG(USBD_DBG, " %s control complete\r\n", driver->name); +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if (driver && driver->control_xfer_cb == callback) { + TU_LOG_USBD("%s control complete\r\n", driver->name); return; } } @@ -331,43 +347,36 @@ void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -tusb_speed_t tud_speed_get(void) -{ +tusb_speed_t tud_speed_get(void) { return (tusb_speed_t) _usbd_dev.speed; } -bool tud_connected(void) -{ +bool tud_connected(void) { return _usbd_dev.connected; } -bool tud_mounted(void) -{ +bool tud_mounted(void) { return _usbd_dev.cfg_num ? true : false; } -bool tud_suspended(void) -{ +bool tud_suspended(void) { return _usbd_dev.suspended; } -bool tud_remote_wakeup(void) -{ +bool tud_remote_wakeup(void) { // only wake up host if this feature is supported and enabled and we are suspended - TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); + TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en); dcd_remote_wakeup(_usbd_rhport); return true; } -bool tud_disconnect(void) -{ +bool tud_disconnect(void) { TU_VERIFY(dcd_disconnect); dcd_disconnect(_usbd_rhport); return true; } -bool tud_connect(void) -{ +bool tud_connect(void) { TU_VERIFY(dcd_connect); dcd_connect(_usbd_rhport); return true; @@ -376,20 +385,19 @@ bool tud_connect(void) //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ -bool tud_inited(void) -{ +bool tud_inited(void) { return _usbd_rhport != RHPORT_INVALID; } -bool tud_init (uint8_t rhport) -{ +bool tud_init(uint8_t rhport) { // skip if already initialized - if ( tud_inited() ) return true; + if (tud_inited()) return true; - TU_LOG(USBD_DBG, "USBD init on controller %u\r\n", rhport); - TU_LOG_INT(USBD_DBG, sizeof(usbd_device_t)); - TU_LOG_INT(USBD_DBG, sizeof(tu_fifo_t)); - TU_LOG_INT(USBD_DBG, sizeof(tu_edpt_stream_t)); + TU_LOG_USBD("USBD init on controller %u\r\n", rhport); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t)); tu_varclr(&_usbd_dev); @@ -404,17 +412,15 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( usbd_app_driver_get_cb ) - { + if (usbd_app_driver_get_cb) { _app_driver = usbd_app_driver_get_cb(&_app_driver_count); } // Init class drivers - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_ASSERT(driver); - TU_LOG(USBD_DBG, "%s init\r\n", driver->name); + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + TU_ASSERT(driver && driver->init); + TU_LOG_USBD("%s init\r\n", driver->name); driver->init(); } @@ -427,31 +433,61 @@ bool tud_init (uint8_t rhport) return true; } -static void configuration_reset(uint8_t rhport) -{ - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_ASSERT(driver, ); +bool tud_deinit(uint8_t rhport) { + // skip if not initialized + if (!tud_inited()) return true; + + TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport); + + // Deinit device controller driver + dcd_int_disable(rhport); + dcd_disconnect(rhport); + dcd_deinit(rhport); + + // Deinit class drivers + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if(driver && driver->deinit) { + TU_LOG_USBD("%s deinit\r\n", driver->name); + driver->deinit(); + } + } + + // Deinit device queue & task + osal_queue_delete(_usbd_q); + _usbd_q = NULL; + +#if OSAL_MUTEX_REQUIRED + // TODO make sure there is no task waiting on this mutex + osal_mutex_delete(_usbd_mutex); + _usbd_mutex = NULL; +#endif + + _usbd_rhport = RHPORT_INVALID; + + return true; +} + +static void configuration_reset(uint8_t rhport) { + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + TU_ASSERT(driver,); driver->reset(rhport); } tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping + memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } -static void usbd_reset(uint8_t rhport) -{ +static void usbd_reset(uint8_t rhport) { configuration_reset(rhport); usbd_control_reset(); } -bool tud_task_event_ready(void) -{ +bool tud_task_event_ready(void) { // Skip if stack is not initialized - if ( !tud_inited() ) return false; - + if (!tud_inited()) return false; return !osal_queue_empty(_usbd_q); } @@ -459,139 +495,126 @@ bool tud_task_event_ready(void) * This top level thread manages all device controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. * - @code - int main(void) - { + int main(void) { application_init(); tusb_init(); - while(1) // the mainloop - { + while(1) { // the mainloop application_code(); tud_task(); // tinyusb device task } } - @endcode */ -void tud_task_ext(uint32_t timeout_ms, bool in_isr) -{ +void tud_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized - if ( !tud_inited() ) return; + if (!tud_inited()) return; // Loop until there is no more events in the queue - while (1) - { + while (1) { dcd_event_t event; - if ( !osal_queue_receive(_usbd_q, &event, timeout_ms) ) return; + if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return; -#if CFG_TUSB_DEBUG >= 2 - if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG(USBD_DBG, "\r\n"); // extra line for setup - TU_LOG(USBD_DBG, "USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup + TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); #endif - switch ( event.event_id ) - { + switch (event.event_id) { case DCD_EVENT_BUS_RESET: - TU_LOG(USBD_DBG, ": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); + TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; - break; + break; case DCD_EVENT_UNPLUGGED: - TU_LOG(USBD_DBG, "\r\n"); + TU_LOG_USBD("\r\n"); usbd_reset(event.rhport); - - // invoke callback if (tud_umount_cb) tud_umount_cb(); - break; + break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG_PTR(USBD_DBG, &event.setup_received); - TU_LOG(USBD_DBG, "\r\n"); + _usbd_dev.setup_count--; + TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); + if (_usbd_dev.setup_count) { + TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n"); + break; + } // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set _usbd_dev.connected = 1; // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0; _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0; // Process control request - if ( !process_control_request(event.rhport, &event.setup_received) ) - { - TU_LOG(USBD_DBG, " Stall EP0\r\n"); + if (!process_control_request(event.rhport, &event.setup_received)) { + TU_LOG_USBD(" Stall EP0\r\n"); // Failed -> stall both control endpoint IN and OUT dcd_edpt_stall(event.rhport, 0); dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); } - break; + break; - case DCD_EVENT_XFER_COMPLETE: - { + case DCD_EVENT_XFER_COMPLETE: { // Invoke the class callback associated with the endpoint address uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG(USBD_DBG, "on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].busy = 0; _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; - if ( 0 == epnum ) - { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); - TU_ASSERT(driver, ); + if (0 == epnum) { + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, + event.xfer_complete.len); + } else { + usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); + TU_ASSERT(driver,); - TU_LOG(USBD_DBG, " %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + TU_LOG_USBD(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } + break; } - break; case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected - if ( _usbd_dev.connected ) - { - TU_LOG(USBD_DBG, ": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); + if (_usbd_dev.connected) { + TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); - }else - { - TU_LOG(USBD_DBG, " Skipped\r\n"); + } else { + TU_LOG_USBD(" Skipped\r\n"); } - break; + break; case DCD_EVENT_RESUME: - if ( _usbd_dev.connected ) - { - TU_LOG(USBD_DBG, "\r\n"); + if (_usbd_dev.connected) { + TU_LOG_USBD("\r\n"); if (tud_resume_cb) tud_resume_cb(); - }else - { - TU_LOG(USBD_DBG, " Skipped\r\n"); + } else { + TU_LOG_USBD(" Skipped\r\n"); } - break; + break; case USBD_EVENT_FUNC_CALL: - TU_LOG(USBD_DBG, "\r\n"); - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; + TU_LOG_USBD("\r\n"); + if (event.func_call.func) event.func_call.func(event.func_call.param); + break; case DCD_EVENT_SOF: default: TU_BREAKPOINT(); - break; + break; } #if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO @@ -606,44 +629,37 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) //--------------------------------------------------------------------+ // Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) -{ +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { usbd_control_set_complete_callback(driver->control_xfer_cb); - TU_LOG(USBD_DBG, " %s control request\r\n", driver->name); + TU_LOG_USBD(" %s control request\r\n", driver->name); return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); } // This handles the actual request and its response. -// return false will cause its caller to stall control endpoint -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ +// Returns false if unable to complete the request, causing caller to stall control endpoints. +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { usbd_control_set_complete_callback(NULL); - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request - if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) - { + if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { TU_VERIFY(tud_vendor_control_xfer_cb); usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } -#if CFG_TUSB_DEBUG >= 2 - if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) - { - TU_LOG(USBD_DBG, " %s", tu_str_std_request[p_request->bRequest]); - if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG(USBD_DBG, "\r\n"); +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) { + TU_LOG_USBD(" %s", tu_str_std_request[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG_USBD("\r\n"); } #endif - switch ( p_request->bmRequestType_bit.recipient ) - { + switch ( p_request->bmRequestType_bit.recipient ) { //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: - if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) { uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); @@ -654,15 +670,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return invoke_class_control(rhport, driver, p_request); } - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported TU_BREAKPOINT(); return false; } - switch ( p_request->bRequest ) - { + switch ( p_request->bRequest ) { case TUSB_REQ_SET_ADDRESS: // Depending on mcu, status phase could be sent either before or after changing device address, // or even require stack to not response with status at all @@ -673,24 +687,20 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.addressed = 1; break; - case TUSB_REQ_GET_CONFIGURATION: - { + case TUSB_REQ_GET_CONFIGURATION: { uint8_t cfg_num = _usbd_dev.cfg_num; tud_control_xfer(rhport, p_request, &cfg_num, 1); } break; - case TUSB_REQ_SET_CONFIGURATION: - { + case TUSB_REQ_SET_CONFIGURATION: { uint8_t const cfg_num = (uint8_t) p_request->wValue; // Only process if new configure is different - if (_usbd_dev.cfg_num != cfg_num) - { - if ( _usbd_dev.cfg_num ) - { + if (_usbd_dev.cfg_num != cfg_num) { + if ( _usbd_dev.cfg_num ) { // already configured: need to clear all endpoints and driver first - TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); + TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); // close all non-control endpoints, cancel all pending transfers if any dcd_edpt_close_all(rhport); @@ -702,8 +712,14 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.speed = speed; // restore speed } - // switch to new configuration if not zero - if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + // Handle the new configuration and execute the corresponding callback + if ( cfg_num ) { + // switch to new configuration if not zero + TU_ASSERT( process_set_config(rhport, cfg_num) ); + if ( tud_mount_cb ) tud_mount_cb(); + } else { + if ( tud_umount_cb ) tud_umount_cb(); + } } _usbd_dev.cfg_num = cfg_num; @@ -719,7 +735,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); + TU_LOG_USBD(" Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; @@ -730,22 +746,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); + TU_LOG_USBD(" Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); break; - case TUSB_REQ_GET_STATUS: - { + case TUSB_REQ_GET_STATUS: { // Device status bit mask // - Bit 0: Self Powered // - Bit 1: Remote Wakeup enabled uint16_t status = (uint16_t) ((_usbd_dev.self_powered ? 1u : 0u) | (_usbd_dev.remote_wakeup_en ? 2u : 0u)); tud_control_xfer(rhport, p_request, &status, 2); + break; } - break; // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; @@ -753,8 +768,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; //------------- Class/Interface Specific Request -------------// - case TUSB_REQ_RCPT_INTERFACE: - { + case TUSB_REQ_RCPT_INTERFACE: { uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); @@ -763,25 +777,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) - { + if ( !invoke_class_control(rhport, driver, p_request) ) { // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - switch(p_request->bRequest) - { + switch(p_request->bRequest) { case TUSB_REQ_GET_INTERFACE: case TUSB_REQ_SET_INTERFACE: // Clear complete callback if driver set since it can also stall the request. usbd_control_set_complete_callback(NULL); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) - { + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) { uint8_t alternate = 0; tud_control_xfer(rhport, p_request, &alternate, 1); - }else - { + }else { tud_control_status(rhport, p_request); } break; @@ -789,54 +799,42 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const default: return false; } } + break; } - break; //------------- Endpoint Request -------------// - case TUSB_REQ_RCPT_ENDPOINT: - { + case TUSB_REQ_RCPT_ENDPOINT: { uint8_t const ep_addr = tu_u16_low(p_request->wIndex); uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Forward class request to its driver TU_VERIFY(driver); return invoke_class_control(rhport, driver, p_request); - } - else - { + } else { // Handle STD request to endpoint - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_STATUS: - { + switch ( p_request->bRequest ) { + case TUSB_REQ_GET_STATUS: { uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; tud_control_xfer(rhport, p_request, &status, 2); } break; case TUSB_REQ_CLEAR_FEATURE: - case TUSB_REQ_SET_FEATURE: - { - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) - { + case TUSB_REQ_SET_FEATURE: { + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) { + if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) { usbd_edpt_clear_stall(rhport, ep_addr); - }else - { + }else { usbd_edpt_stall(rhport, ep_addr); } } - if (driver) - { + if (driver) { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will also forward std request targeted endpoint to class drivers as well @@ -852,14 +850,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; + default: + TU_BREAKPOINT(); + return false; } } } break; // Unknown recipient - default: TU_BREAKPOINT(); return false; + default: + TU_BREAKPOINT(); + return false; } return true; @@ -913,7 +915,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) { // Open successfully - TU_LOG(USBD_DBG, " %s opened\r\n", driver->name); + TU_LOG_USBD(" %s opened\r\n", driver->name); // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or // BTH (even CDC) with class in device descriptor (single interface) @@ -956,9 +958,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); } - // invoke callback - if (tud_mount_cb) tud_mount_cb(); - return true; } @@ -972,7 +971,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { case TUSB_DESC_DEVICE: { - TU_LOG(USBD_DBG, " Device\r\n"); + TU_LOG_USBD(" Device\r\n"); void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); @@ -996,7 +995,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_BOS: { - TU_LOG(USBD_DBG, " BOS\r\n"); + TU_LOG_USBD(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; @@ -1018,12 +1017,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if ( desc_type == TUSB_DESC_CONFIGURATION ) { - TU_LOG(USBD_DBG, " Configuration[%u]\r\n", desc_index); + TU_LOG_USBD(" Configuration[%u]\r\n", desc_index); desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); }else { // Host only request this after getting Device Qualifier descriptor - TU_LOG(USBD_DBG, " Other Speed Configuration\r\n"); + TU_LOG_USBD(" Other Speed Configuration\r\n"); TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); } @@ -1039,7 +1038,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_STRING: { - TU_LOG(USBD_DBG, " String[%u]\r\n", desc_index); + TU_LOG_USBD(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); @@ -1052,7 +1051,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_DEVICE_QUALIFIER: { - TU_LOG(USBD_DBG, " Device Qualifier\r\n"); + TU_LOG_USBD(" Device Qualifier\r\n"); TU_VERIFY( tud_descriptor_device_qualifier_cb ); @@ -1071,66 +1070,69 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ -TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const * event, bool in_isr) -{ - switch (event->event_id) - { +TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) { + bool send = false; + switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - break; + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + send = true; + break; case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected - if ( _usbd_dev.connected ) - { + if (_usbd_dev.connected) { _usbd_dev.suspended = 1; - osal_queue_send(_usbd_q, event, in_isr); + send = true; } - break; + break; case DCD_EVENT_RESUME: // skip event if not connected (especially required for SAMD) - if ( _usbd_dev.connected ) - { + if (_usbd_dev.connected) { _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); + send = true; } - break; + break; case DCD_EVENT_SOF: - // SOF driver handler in ISR context - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if (driver && driver->sof) - { - driver->sof(event->rhport, event->sof.frame_count); - } - } - // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational - if ( _usbd_dev.suspended ) - { + if (_usbd_dev.suspended) { _usbd_dev.suspended = 0; - dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; - osal_queue_send(_usbd_q, &event_resume, in_isr); + dcd_event_t const event_resume = {.rhport = event->rhport, .event_id = DCD_EVENT_RESUME}; + queue_event(&event_resume, in_isr); + } + + // SOF driver handler in ISR context + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if (driver && driver->sof) { + driver->sof(event->rhport, event->sof.frame_count); + } } // skip osal queue for SOF in usbd task - break; + break; + + case DCD_EVENT_SETUP_RECEIVED: + _usbd_dev.setup_count++; + send = true; + break; default: - osal_queue_send(_usbd_q, event, in_isr); - break; + send = true; + break; + } + + if (send) { + queue_event(event, in_isr); } } @@ -1174,26 +1176,22 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count } // Helper to defer an isr function -void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) -{ - dcd_event_t event = - { +void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) { + dcd_event_t event = { .rhport = 0, .event_id = USBD_EVENT_FUNC_CALL, }; - event.func_call.func = func; event.func_call.param = param; - dcd_event_handler(&event, in_isr); + queue_event(&event, in_isr); } //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); @@ -1202,59 +1200,59 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) return dcd_edpt_open(rhport, desc_ep); } -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; // TODO add this check later, also make sure we don't starve an out endpoint while suspending // TU_VERIFY(tud_ready()); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; return tu_edpt_claim(ep_state, _usbd_mutex); } -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; return tu_edpt_release(ep_state, _usbd_mutex); } -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // TODO skip ready() check for now since enumeration also use this API // TU_VERIFY(tud_ready()); - TU_LOG(USBD_DBG, " Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); + TU_LOG_USBD(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); +#if CFG_TUD_LOG_LEVEL >= 3 + if(dir == TUSB_DIR_IN) { + TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2); + } +#endif // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; - if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) - { + if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)) { return true; - }else - { + } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG(USBD_DBG, "FAILED\r\n"); + TU_LOG_USBD("FAILED\r\n"); TU_BREAKPOINT(); return false; } @@ -1264,117 +1262,100 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG(USBD_DBG, " Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG_USBD(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) - { - TU_LOG(USBD_DBG, "OK\r\n"); + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { + TU_LOG_USBD("OK\r\n"); return true; - }else - { + } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG(USBD_DBG, "failed\r\n"); + TU_LOG_USBD("failed\r\n"); TU_BREAKPOINT(); return false; } } -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); return _usbd_dev.ep_status[epnum][dir].busy; } -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // only stalled if currently cleared - if ( !_usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; - } + TU_LOG_USBD(" Stall EP %02X\r\n", ep_addr); + dcd_edpt_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = 1; + _usbd_dev.ep_status[epnum][dir].busy = 1; } -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // only clear if currently stalled - if ( _usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - } + TU_LOG_USBD(" Clear Stall EP %02X\r\n", ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; } -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); return _usbd_dev.ep_status[epnum][dir].stalled; } /** * usbd_edpt_close will disable an endpoint. - * * In progress transfers on this EP may be delivered after this call. - * */ -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; TU_ASSERT(dcd_edpt_close, /**/); - TU_LOG(USBD_DBG, " CLOSING Endpoint: 0x%02X\r\n", ep_addr); + TU_LOG_USBD(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return; } -void usbd_sof_enable(uint8_t rhport, bool en) -{ +void usbd_sof_enable(uint8_t rhport, bool en) { rhport = _usbd_rhport; // TODO: Check needed if all drivers including the user sof_cb does not need an active SOF ISR any more. @@ -1382,8 +1363,7 @@ void usbd_sof_enable(uint8_t rhport, bool en) dcd_sof_enable(rhport, en); } -bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) -{ +bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { rhport = _usbd_rhport; TU_ASSERT(dcd_edpt_iso_alloc); @@ -1392,20 +1372,19 @@ bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packe return dcd_edpt_iso_alloc(rhport, ep_addr, largest_packet_size); } -bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ +bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(desc_ep->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(dcd_edpt_iso_activate); TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return dcd_edpt_iso_activate(rhport, desc_ep); } diff --git a/test-devices/composite-stm32/lib/tinyusb/device/usbd.h b/test-devices/composite-stm32/lib/tinyusb/device/usbd.h index 255e5a84..f3673404 100644 --- a/test-devices/composite-stm32/lib/tinyusb/device/usbd.h +++ b/test-devices/composite-stm32/lib/tinyusb/device/usbd.h @@ -37,9 +37,12 @@ extern "C" { // Application API //--------------------------------------------------------------------+ -// Init device stack +// Init device stack on roothub port bool tud_init (uint8_t rhport); +// Deinit device stack on roothub port +bool tud_deinit(uint8_t rhport); + // Check if device stack is already initialized bool tud_inited(void); @@ -50,8 +53,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop TU_ATTR_ALWAYS_INLINE static inline -void tud_task (void) -{ +void tud_task (void) { tud_task_ext(UINT32_MAX, false); } @@ -80,8 +82,7 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } @@ -148,6 +149,9 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); // Invoked when usb bus is resumed TU_ATTR_WEAK void tud_resume_cb(void); +// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext() +void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); + // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); @@ -217,8 +221,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC Call */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC ACM: support line request + send break */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 6,\ /* CDC Union */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ /* Endpoint Notification */\ @@ -347,8 +351,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 -#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx +#define TUD_AUDIO_DESC_IAD(_firstitf, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitf, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 @@ -392,6 +396,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // For more channels, add definitions here +/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */ +#define TUD_AUDIO_DESC_STD_AC_INT_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AC_INT_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval + /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ @@ -420,7 +429,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source @@ -443,7 +452,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -467,7 +476,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) @@ -492,7 +501,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -516,7 +525,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) @@ -540,7 +549,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -564,7 +573,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ @@ -773,10 +782,6 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 #define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -#define CFG_TUD_BTH_ISO_ALT_COUNT 0 -#endif - // Length of template descriptor: 38 bytes + number of ISO alternatives * 23 #define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) diff --git a/test-devices/composite-stm32/lib/tinyusb/device/usbd_control.c b/test-devices/composite-stm32/lib/tinyusb/device/usbd_control.c index ea8eef28..35cce1f7 100644 --- a/test-devices/composite-stm32/lib/tinyusb/device/usbd_control.c +++ b/test-devices/composite-stm32/lib/tinyusb/device/usbd_control.c @@ -32,30 +32,38 @@ #include "tusb.h" #include "device/usbd_pvt.h" -#if CFG_TUSB_DEBUG >= 2 +//--------------------------------------------------------------------+ +// Callback weak stubs (called if application does not provide) +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { + (void) rhport; + (void) request; +} + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif -enum -{ +enum { EDPT_CTRL_OUT = 0x00, - EDPT_CTRL_IN = 0x80 + EDPT_CTRL_IN = 0x80 }; -typedef struct -{ +typedef struct { tusb_control_request_t request; - uint8_t* buffer; uint16_t data_len; uint16_t total_xferred; - usbd_control_xfer_cb_t complete_cb; } usbd_control_xfer_t; tu_static usbd_control_xfer_t _ctrl_xfer; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ @@ -63,20 +71,18 @@ tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ // Queue ZLP status transaction -static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) -{ +static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const* request) { // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; +bool tud_control_status(uint8_t rhport, tusb_control_request_t const* request) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; + _ctrl_xfer.data_len = 0; return _status_stage_xact(rhport, request); } @@ -84,16 +90,15 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) // Queue a transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet -static bool _data_stage_xact(uint8_t rhport) -{ - uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); +static bool _data_stage_xact(uint8_t rhport) { + uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, + CFG_TUD_ENDPOINT0_SIZE); uint8_t ep_addr = EDPT_CTRL_OUT; - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) - { + if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { ep_addr = EDPT_CTRL_IN; - if ( xact_len ) { + if (xact_len) { TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); } } @@ -103,29 +108,24 @@ static bool _data_stage_xact(uint8_t rhport) // Transmit data to/from the control endpoint. // If the request's wLength is zero, a status packet is sent instead. -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = (uint8_t*) buffer; +bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, void* buffer, uint16_t len) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = (uint8_t*) buffer; _ctrl_xfer.total_xferred = 0U; - _ctrl_xfer.data_len = tu_min16(len, request->wLength); + _ctrl_xfer.data_len = tu_min16(len, request->wLength); - if (request->wLength > 0U) - { - if(_ctrl_xfer.data_len > 0U) - { + if (request->wLength > 0U) { + if (_ctrl_xfer.data_len > 0U) { TU_ASSERT(buffer); } // TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); // Data stage - TU_ASSERT( _data_stage_xact(rhport) ); - } - else - { + TU_ASSERT(_data_stage_xact(rhport)); + } else { // Status stage - TU_ASSERT( _status_stage_xact(rhport, request) ); + TU_ASSERT(_status_stage_xact(rhport, request)); } return true; @@ -134,49 +134,42 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo //--------------------------------------------------------------------+ // USBD API //--------------------------------------------------------------------+ - void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void usbd_control_set_request(tusb_control_request_t const* request); +void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp); +bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void usbd_control_reset(void) -{ +void usbd_control_reset(void) { tu_varclr(&_ctrl_xfer); } // Set complete callback -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) -{ +void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) { _ctrl_xfer.complete_cb = fp; } // for dcd_set_address where DCD is responsible for status response -void usbd_control_set_request(tusb_control_request_t const *request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; +void usbd_control_set_request(tusb_control_request_t const* request) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; + _ctrl_xfer.data_len = 0; } // callback when a transaction complete on // - DATA stage of control endpoint or // - Status stage -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; // Endpoint Address is opposite to direction bit, this is Status Stage complete event - if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) - { + if (tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction) { TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - if (_ctrl_xfer.complete_cb) - { + if (_ctrl_xfer.complete_cb) { // TODO refactor with usbd_driver_print_control_complete_name _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); } @@ -184,11 +177,10 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result return true; } - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) - { + if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); + TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += (uint16_t) xferred_bytes; @@ -196,37 +188,32 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // Data Stage is complete when all request's length are transferred or // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) - { + if ((_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || + (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE)) { // DATA stage is complete bool is_ok = true; // invoke complete callback if set // callback can still stall control in status phase e.g out data does not make sense - if ( _ctrl_xfer.complete_cb ) - { - #if CFG_TUSB_DEBUG >= 2 + if (_ctrl_xfer.complete_cb) { + #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); } - if ( is_ok ) - { + if (is_ok) { // Send status - TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); - }else - { + TU_ASSERT(_status_stage_xact(rhport, &_ctrl_xfer.request)); + } else { // Stall both IN and OUT control endpoint dcd_edpt_stall(rhport, EDPT_CTRL_OUT); dcd_edpt_stall(rhport, EDPT_CTRL_IN); } - } - else - { + } else { // More data to transfer - TU_ASSERT( _data_stage_xact(rhport) ); + TU_ASSERT(_data_stage_xact(rhport)); } return true; diff --git a/test-devices/composite-stm32/lib/tinyusb/device/usbd_pvt.h b/test-devices/composite-stm32/lib/tinyusb/device/usbd_pvt.h index 8393d346..47752f32 100644 --- a/test-devices/composite-stm32/lib/tinyusb/device/usbd_pvt.h +++ b/test-devices/composite-stm32/lib/tinyusb/device/usbd_pvt.h @@ -23,8 +23,8 @@ * * This file is part of the TinyUSB stack. */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ +#ifndef _TUSB_USBD_PVT_H_ +#define _TUSB_USBD_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -33,17 +33,19 @@ extern "C" { #endif +#define TU_LOG_USBD(...) TU_LOG(CFG_TUD_LOG_LEVEL, __VA_ARGS__) + //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 +typedef struct { + #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* name; #endif void (* init ) (void); + bool (* deinit ) (void); void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); @@ -52,7 +54,7 @@ typedef struct } usbd_class_driver_t; // Invoked when initializing device stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. +// Can be implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; @@ -104,8 +106,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline -bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); } @@ -117,11 +118,10 @@ void usbd_sof_enable(uint8_t rhport, bool en); *------------------------------------------------------------------*/ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - +void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); #ifdef __cplusplus } #endif -#endif /* USBD_PVT_H_ */ +#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/hwcfg_list.md b/test-devices/composite-stm32/lib/tinyusb/dwc2/hwcfg_list.md deleted file mode 100644 index b5590da0..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/dwc2/hwcfg_list.md +++ /dev/null @@ -1,777 +0,0 @@ -# DWC2 Hardware Configuration Registers - -## Broadcom BCM2711 (Pi4) - -dwc2->guid = 2708A000 -dwc2->gsnpsid = 4F54280A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228DDD50 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 1 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 7 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = FF000E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 4080 - -dwc2->ghwcfg4 = 1FF00020 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 0 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 15 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## EFM32GG FS - -dwc2->guid = 0 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228F5910 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 13 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 1F204E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 1 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 498 - -dwc2->ghwcfg4 = 1BF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## ESP32-S2 Fullspeed - -dwc2->guid = 0 -dwc2->gsnpsid = 4F54400A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 224DD930 -hw_cfg2->op_mode = 2 -hw_cfg2->arch = 3 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 1 -hw_cfg2->fs_phy_type = 2 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 9 -hw_cfg2->period_channel_support = 0 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 1 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 22 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = C804B5 -hw_cfg3->xfer_size_width = 10 -hw_cfg3->packet_size_width = 5 -hw_cfg3->otg_enable = 0 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 1 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 23130 - -dwc2->ghwcfg4 = D3F0A030 -hw_cfg4->num_dev_period_in_ep = 10 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 0 -hw_cfg4->hibernation = 1 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 1 -hw_cfg4->acg_enable = 1 -hw_cfg4->utmi_phy_data_width = 1 -hw_cfg4->dev_ctrl_ep_num = 10 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 0 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 0 -hw_cfg4->dedicated_fifos = 0 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 1 - -## STM32F407 and STM32F207 - -STM32F407 and STM32F207 are exactly the same - -### STM32F407 Fullspeed - -dwc2->guid = 1200 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229DCD20 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 3 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 20001E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = FF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 7 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -### STM32F407 Highspeed - -dwc2->guid = 1100 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED590 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 2 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3F403E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 1012 - -dwc2->ghwcfg4 = 17F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F411 Fullspeed - -dwc2->guid = 1200 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229DCD20 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 3 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 20001E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = FF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 7 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F412 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54320A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F723 - -### STM32F723 HighSpeed - -dwc2->guid = 3100 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229FE1D0 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 3 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 8 -hw_cfg2->num_host_ch = 15 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3EED2E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 1006 - -dwc2->ghwcfg4 = 23F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 1 -hw_cfg4->dma_desc_enable = 1 -hw_cfg4->dma_dynamic = 0 - -### STM32F723 Fullspeed - -dwc2->guid = 3000 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F767 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54320A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32H743 (both cores HS) - -dwc2->guid = 2300 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229FE190 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 2 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 8 -hw_cfg2->num_host_ch = 15 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3B8D2E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 952 - -dwc2->ghwcfg4 = E3F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 1 -hw_cfg4->dma_desc_enable = 1 -hw_cfg4->dma_dynamic = 1 - -## STM32L476 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54310A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## GD32VF103 Fullspeed - -dwc2->guid = 1000 -dwc2->gsnpsid = 0 -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 0 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 0 -hw_cfg2->num_dev_ep = 0 -hw_cfg2->num_host_ch = 0 -hw_cfg2->period_channel_support = 0 -hw_cfg2->enable_dynamic_fifo = 0 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 0 -hw_cfg2->host_period_tx_q_depth = 0 -hw_cfg2->dev_token_q_depth = 0 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 0 -hw_cfg3->xfer_size_width = 0 -hw_cfg3->packet_size_width = 0 -hw_cfg3->otg_enable = 0 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 0 - -dwc2->ghwcfg4 = 0 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 0 -hw_cfg4->ahb_freq_min = 0 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 0 -hw_cfg4->vbus_valid_filter_enabled = 0 -hw_cfg4->a_valid_filter_enabled = 0 -hw_cfg4->b_valid_filter_enabled = 0 -hw_cfg4->dedicated_fifos = 0 -hw_cfg4->num_dev_in_eps = 0 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## XMC4500 - -dwc2->guid = AEC000 -dwc2->gsnpsid = 4F54292A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228F5930 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 13 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 27A01E5 -hw_cfg3->xfer_size_width = 5 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 634 - -dwc2->ghwcfg4 = DBF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 1 diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal.h index f092e8ff..8f45ea5c 100644 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal.h +++ b/test-devices/composite-stm32/lib/tinyusb/osal/osal.h @@ -74,15 +74,18 @@ typedef void (*osal_task_func_t)( void * ); // Should be implemented as static inline function in osal_port.h header /* osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); + bool osal_semaphore_delete(osal_semaphore_t semd_hdl); bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); + bool osal_mutex_delete(osal_mutex_t mutex_hdl) bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); bool osal_mutex_unlock(osal_mutex_t mutex_hdl); osal_queue_t osal_queue_create(osal_queue_def_t* qdef); + bool osal_queue_delete(osal_queue_t qhdl); bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec); bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); bool osal_queue_empty(osal_queue_t qhdl); diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_freertos.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_freertos.h deleted file mode 100644 index 477f6489..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_freertos.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_FREERTOS_H_ -#define _TUSB_OSAL_FREERTOS_H_ - -// FreeRTOS Headers -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -#if configSUPPORT_STATIC_ALLOCATION - typedef StaticSemaphore_t osal_semaphore_def_t; - typedef StaticSemaphore_t osal_mutex_def_t; -#else - // not used therefore defined to smallest possible type to save space - typedef uint8_t osal_semaphore_def_t; - typedef uint8_t osal_mutex_def_t; -#endif - -typedef SemaphoreHandle_t osal_semaphore_t; -typedef SemaphoreHandle_t osal_mutex_t; - -// _int_set is not used with an RTOS -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; -#if configSUPPORT_STATIC_ALLOCATION - StaticQueue_t sq; -#endif -}osal_queue_def_t; - -typedef QueueHandle_t osal_queue_t; - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) -{ - if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY; - if (msec == 0) return 0; - - uint32_t ticks = pdMS_TO_TICKS(msec); - - // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms - // we still need to delay at least 1 tick - if (ticks == 0) ticks =1 ; - - return ticks; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - vTaskDelay( pdMS_TO_TICKS(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xSemaphoreCreateBinaryStatic(semdef); -#else - (void) semdef; - return xSemaphoreCreateBinary(); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - if ( !in_isr ) - { - return xSemaphoreGive(sem_hdl) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec)); -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) -{ - xQueueReset(sem_hdl); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xSemaphoreCreateMutexStatic(mdef); -#else - (void) mdef; - return xSemaphoreCreateMutex(); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return xSemaphoreGive(mutex_hdl); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -#else - return xQueueCreate(qdef->depth, qdef->item_sz); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - return xQueueReceive(qhdl, data, _osal_ms2tick(msec)); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if ( !in_isr ) - { - return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return uxQueueMessagesWaiting(qhdl) == 0; -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_mynewt.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_mynewt.h deleted file mode 100644 index b8ea2087..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_mynewt.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef OSAL_MYNEWT_H_ -#define OSAL_MYNEWT_H_ - -#include "os/os.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - os_time_delay( os_time_ms_to_ticks32(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct os_sem osal_semaphore_def_t; -typedef struct os_sem* osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - return os_sem_release(sem_hdl) == OS_OK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_sem_pend(sem_hdl, ticks) == OS_OK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - // TODO implement later -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct os_mutex osal_mutex_def_t; -typedef struct os_mutex* osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_mutex_pend(mutex_hdl, ticks) == OS_OK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mutex_release(mutex_hdl) == OS_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - static struct os_event _name##_##evbuf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - void* evbuf; - - struct os_mempool mpool; - struct os_mempool epool; - - struct os_eventq evq; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; - if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; - - os_eventq_init(&qdef->evq); - return (osal_queue_t) qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - (void) msec; // os_eventq_get() does not take timeout, always behave as msec = WAIT_FOREVER - - struct os_event* ev; - ev = os_eventq_get(&qhdl->evq); - - memcpy(data, ev->ev_arg, qhdl->item_sz); // copy message - os_memblock_put(&qhdl->mpool, ev->ev_arg); // put back mem block - os_memblock_put(&qhdl->epool, ev); // put back ev block - - return true; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - (void) in_isr; - - // get a block from mem pool for data - void* ptr = os_memblock_get(&qhdl->mpool); - if (!ptr) return false; - memcpy(ptr, data, qhdl->item_sz); - - // get a block from event pool to put into queue - struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool); - if (!ev) - { - os_memblock_put(&qhdl->mpool, ptr); - return false; - } - tu_memclr(ev, sizeof(struct os_event)); - ev->ev_arg = ptr; - - os_eventq_put(&qhdl->evq, ev); - - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return STAILQ_EMPTY(&qhdl->evq.evq_list); -} - - -#ifdef __cplusplus - } -#endif - -#endif /* OSAL_MYNEWT_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_none.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_none.h index 5f407378..c93f7a86 100644 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_none.h +++ b/test-devices/composite-stm32/lib/tinyusb/osal/osal_none.h @@ -24,11 +24,11 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OSAL_NONE_H_ -#define _TUSB_OSAL_NONE_H_ +#ifndef TUSB_OSAL_NONE_H_ +#define TUSB_OSAL_NONE_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ @@ -37,45 +37,46 @@ #if CFG_TUH_ENABLED // currently only needed/available in host mode -void osal_task_delay(uint32_t msec); +TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { volatile uint16_t count; -}osal_semaphore_def_t; +} osal_semaphore_def_t; typedef osal_semaphore_def_t* osal_semaphore_t; -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { semdef->count = 0; return semdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { + (void) semd_hdl; + return true; // nothing to do +} + + +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; sem_hdl->count++; return true; } // TODO blocking for now -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { (void) msec; - while (sem_hdl->count == 0) { } + while (sem_hdl->count == 0) {} sem_hdl->count--; return true; } -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) { sem_hdl->count = 0; } @@ -90,19 +91,21 @@ typedef osal_semaphore_t osal_mutex_t; // Note: multiple cores MCUs usually do provide IPC API for mutex // or we can use std atomic function -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { mdef->count = 1; return mdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { + (void) mutex_hdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { return osal_semaphore_wait(mutex_hdl, msec); } -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return osal_semaphore_post(mutex_hdl, false); } @@ -119,11 +122,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd //--------------------------------------------------------------------+ #include "common/tusb_fifo.h" -typedef struct -{ - void (*interrupt_set)(bool); +typedef struct { + void (* interrupt_set)(bool); tu_fifo_t ff; -}osal_queue_def_t; +} osal_queue_def_t; typedef osal_queue_def_t* osal_queue_t; @@ -136,27 +138,28 @@ typedef osal_queue_def_t* osal_queue_t; } // lock queue by disable USB interrupt -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) { // disable dcd/hcd interrupt qhdl->interrupt_set(false); } // unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { // enable dcd/hcd interrupt qhdl->interrupt_set(true); } -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { + (void) qhdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { (void) msec; // not used, always behave as msec = 0 _osal_q_lock(qhdl); @@ -166,8 +169,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { if (!in_isr) { _osal_q_lock(qhdl); } @@ -178,20 +180,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void _osal_q_unlock(qhdl); } - TU_ASSERT(success); - return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { // Skip queue lock/unlock since this function is primarily called // with interrupt disabled before going into low power mode return tu_fifo_empty(&qhdl->ff); } #ifdef __cplusplus - } +} #endif -#endif /* _TUSB_OSAL_NONE_H_ */ +#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_pico.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_pico.h deleted file mode 100644 index e6efa096..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_pico.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_PICO_H_ -#define _TUSB_OSAL_PICO_H_ - -#include "pico/time.h" -#include "pico/sem.h" -#include "pico/mutex.h" -#include "pico/critical_section.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - sleep_ms(msec); -} - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - sem_init(semdef, 0, 255); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_release(sem_hdl); - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - return sem_acquire_timeout_ms(sem_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_reset(sem_hdl, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, *osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mutex_init(mdef); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return mutex_enter_timeout_ms(mutex_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - mutex_exit(mutex_hdl); - return true; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -typedef struct -{ - tu_fifo_t ff; - struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section -} osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) -{ - critical_section_enter_blocking(&qhdl->critsec); -} - -// unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - critical_section_exit(&qhdl->critsec); -} - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - critical_section_init(&qdef->critsec); - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - (void) msec; // not used, always behave as msec = 0 - - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - (void) in_isr; - - _osal_q_lock(qhdl); - bool success = tu_fifo_write(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - TU_ASSERT(success); - - return success; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single - // volatile read. - - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtthread.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtthread.h deleted file mode 100644 index 18eb9c69..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtthread.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 tfx2001 (2479727366@qq.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTTHREAD_H_ -#define _TUSB_OSAL_RTTHREAD_H_ - -// RT-Thread Headers -#include "rtthread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { - rt_thread_mdelay(msec); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct rt_semaphore osal_semaphore_def_t; -typedef rt_sem_t osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t -osal_semaphore_create(osal_semaphore_def_t *semdef) { - rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; - return rt_sem_release(sem_hdl) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { - return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct rt_mutex osal_mutex_def_t; -typedef rt_mutex_t osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { - rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { - return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { - return rt_mutex_release(mutex_hdl) == RT_EOK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth]; \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct { - uint16_t depth; - uint16_t item_sz; - void *buf; - - struct rt_messagequeue sq; -} osal_queue_def_t; - -typedef rt_mq_t osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { - rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, - qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO); - return &(qdef->sq); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { - - rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec); - return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - (void) in_isr; - return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { - return (qhdl->entry) == 0; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtx4.h b/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtx4.h deleted file mode 100644 index e443135e..00000000 --- a/test-devices/composite-stm32/lib/tinyusb/osal/osal_rtx4.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Tian Yunhao (t123yh) - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTX4_H_ -#define _TUSB_OSAL_RTX4_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - uint16_t hi = msec >> 16; - uint16_t lo = msec; - while (hi--) { - os_dly_wait(0xFFFE); - } - os_dly_wait(lo); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { - if (msec == OSAL_TIMEOUT_WAIT_FOREVER) - return 0xFFFF; - else if (msec >= 0xFFFE) - return 0xFFFE; - else - return msec; -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef OS_SEM osal_semaphore_def_t; -typedef OS_ID osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline OS_ID osal_semaphore_create(osal_semaphore_def_t* semdef) { - os_sem_init(semdef, 0); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - if ( !in_isr ) { - os_sem_send(sem_hdl); - } else { - isr_sem_send(sem_hdl); - } - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { - return os_sem_wait(sem_hdl, msec2wait(msec)) != OS_R_TMO; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - // TODO: implement -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef OS_MUT osal_mutex_def_t; -typedef OS_ID osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - os_mut_init(mdef); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mut_release(mutex_hdl) == OS_R_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - os_mbx_declare(_name##__mbox, _depth); \ - _declare_box(_name##__pool, sizeof(_type), _depth); \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .pool = _name##__pool, .mbox = _name##__mbox }; - - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - U32* pool; - U32* mbox; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4); - _init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz); - return qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - void* buf; - os_mbx_wait(qhdl->mbox, &buf, msec2wait(msec)); - memcpy(data, buf, qhdl->item_sz); - _free_box(qhdl->pool, buf); - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - void* buf = _alloc_box(qhdl->pool); - memcpy(buf, data, qhdl->item_sz); - if ( !in_isr ) - { - os_mbx_send(qhdl->mbox, buf, 0xFFFF); - } - else - { - isr_mbx_send(qhdl->mbox, buf); - } - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return os_mbx_check(qhdl->mbox) == qhdl->depth; -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c b/test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c similarity index 53% rename from test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c rename to test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 30a2e9c8..a26c6689 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c +++ b/test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -44,6 +44,7 @@ * L0x2, L0x3 1024 byte buffer * L1 512 byte buffer * L4x2, L4x3 1024 byte buffer + * G0 2048 byte buffer * * To use this driver, you must: * - If you are using a device with crystal-less USB, set up the clock recovery system (CRS) @@ -106,9 +107,9 @@ #include "device/dcd.h" #ifdef TUP_USBIP_FSDEV_STM32 - // Undefine to reduce the dependence on HAL - #undef USE_HAL_DRIVER - #include "dcd_stm32_fsdev_pvt_st.h" +// Undefine to reduce the dependence on HAL +#undef USE_HAL_DRIVER +#include "portable/st/stm32_fsdev/dcd_stm32_fsdev.h" #endif /***************************************************** @@ -118,17 +119,17 @@ // HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM // (8u here would mean 8 IN and 8 OUT) #ifndef MAX_EP_COUNT -# define MAX_EP_COUNT 8U +#define MAX_EP_COUNT 8U #endif // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef DCD_STM32_BTABLE_BASE -# define DCD_STM32_BTABLE_BASE 0U +#define DCD_STM32_BTABLE_BASE 0U #endif -#ifndef DCD_STM32_BTABLE_LENGTH -# define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) +#ifndef DCD_STM32_BTABLE_SIZE +#define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE) #endif /*************************************************** @@ -136,7 +137,7 @@ */ TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT, "Only 8 endpoints supported on the hardware"); -TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LENGTH), "BTABLE does not fit in PMA RAM"); +TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_SIZE)) <= (FSDEV_PMA_SIZE), "BTABLE does not fit in PMA RAM"); TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); //--------------------------------------------------------------------+ @@ -144,21 +145,18 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne //--------------------------------------------------------------------+ // One of these for every EP IN & OUT, uses a bit of RAM.... -typedef struct -{ - uint8_t * buffer; - tu_fifo_t * ff; +typedef struct { + uint8_t *buffer; + tu_fifo_t *ff; uint16_t total_len; uint16_t queued_len; - uint16_t pma_ptr; uint16_t max_packet_size; - uint16_t pma_alloc_size; - uint8_t ep_idx; // index for USB_EPnR register + uint8_t ep_idx; // index for USB_EPnR register + bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask } xfer_ctl_t; // EP allocator -typedef struct -{ +typedef struct { uint8_t ep_num; uint8_t ep_type; bool allocated[2]; @@ -178,28 +176,25 @@ static uint8_t remoteWakeCountdown; // When wake is requested // into the stack. static void dcd_handle_bus_reset(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix); +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); +static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr); static void dcd_ep_ctr_handler(void); // PMA allocation/access -static uint8_t open_ep_count; static uint16_t ep_buf_ptr; ///< Points to first free memory location -static void dcd_pma_alloc_reset(void); -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length); -static void dcd_pma_free(uint8_t ep_addr); -static void dcd_ep_free(uint8_t ep_addr); +static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes); +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes); -static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); -static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); +static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); +static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); //--------------------------------------------------------------------+ // Inline helper //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) +TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint32_t ep_addr) { uint8_t epnum = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); @@ -209,22 +204,11 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) return &xfer_status[epnum][dir]; } -// Using a function due to better type checks -// This seems better than having to do type casts everywhere else -TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { - *reg = (uint16_t)(*reg & ~mask); -} - -// Bits in ISTR are cleared upon writing 0 -TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint16_t mask) { - USB->ISTR = ~mask; -} - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -void dcd_init (uint8_t rhport) +void dcd_init(uint8_t rhport) { /* Clocks should already be enabled */ /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ @@ -232,40 +216,41 @@ void dcd_init (uint8_t rhport) /* The RM mentions to use a special ordering of PDWN and FRES, but this isn't done in HAL. * Here, the RM is followed. */ - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } - reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown + + USB->CNTR &= ~USB_CNTR_PDWN; + // Wait startup time, for F042 and F070, this is <= 1 us. - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } USB->CNTR = 0; // Enable USB +#if !defined(STM32G0) && !defined(STM32H5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address USB->BTABLE = DCD_STM32_BTABLE_BASE; - +#endif USB->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled - for(uint32_t i=0; iCNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); // Enable pull-up if supported - if ( dcd_connect ) dcd_connect(rhport); + if (dcd_connect) { + dcd_connect(rhport); + } } // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. @@ -274,14 +259,14 @@ void dcd_init (uint8_t rhport) // Disable internal D+ PU void dcd_disconnect(uint8_t rhport) { - (void) rhport; + (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } // Enable internal D+ PU void dcd_connect(uint8_t rhport) { - (void) rhport; + (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } @@ -289,60 +274,54 @@ void dcd_connect(uint8_t rhport) // Disable internal D+ PU void dcd_disconnect(uint8_t rhport) { - (void) rhport; + (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } // Enable internal D+ PU void dcd_connect(uint8_t rhport) { - (void) rhport; + (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } #endif void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; - (void) en; + (void)rhport; + (void)en; - if (en) - { + if (en) { USB->CNTR |= USB_CNTR_SOFM; - } - else - { - USB->CNTR &= (uint16_t) ~USB_CNTR_SOFM; + } else { + USB->CNTR &= ~USB_CNTR_SOFM; } } // Enable device interrupt -void dcd_int_enable (uint8_t rhport) +void dcd_int_enable(uint8_t rhport) { (void)rhport; // Member here forces write to RAM before allowing ISR to execute __DSB(); __ISB(); -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || \ - CFG_TUSB_MCU == OPT_MCU_STM32L4 +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4 NVIC_EnableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 NVIC_EnableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to enable the right IRQs. - #ifdef SYSCFG_CFGR1_USB_IT_RMP - if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) - { +// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from +// shared USB/CAN IRQs to separate CAN and USB IRQs. +// This dynamically checks if this remap is active to enable the right IRQs. +#ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); - } - else - #endif + } else +#endif { NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); @@ -358,6 +337,16 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 +#ifdef STM32G0B0xx + NVIC_EnableIRQ(USB_IRQn); +#else + NVIC_EnableIRQ(USB_UCPD1_2_IRQn); +#endif + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + NVIC_EnableIRQ(USB_DRD_FS_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); @@ -366,7 +355,7 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_FS_IRQn); #else - #error Unknown arch in USB driver +#error Unknown arch in USB driver #endif } @@ -375,24 +364,21 @@ void dcd_int_disable(uint8_t rhport) { (void)rhport; -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || \ - CFG_TUSB_MCU == OPT_MCU_STM32L4 +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4 NVIC_DisableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 NVIC_DisableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to disable the right IRQs. - #ifdef SYSCFG_CFGR1_USB_IT_RMP - if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) - { +// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from +// shared USB/CAN IRQs to separate CAN and USB IRQs. +// This dynamically checks if this remap is active to disable the right IRQs. +#ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); - } - else - #endif + } else +#endif { NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn); NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn); @@ -408,6 +394,16 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 +#ifdef STM32G0B0xx + NVIC_DisableIRQ(USB_IRQn); +#else + NVIC_DisableIRQ(USB_UCPD1_2_IRQn); +#endif + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + NVIC_DisableIRQ(USB_DRD_FS_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); @@ -416,7 +412,7 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_FS_IRQn); #else - #error Unknown arch in USB driver +#error Unknown arch in USB driver #endif // CMSIS has a membar after disabling interrupts @@ -425,8 +421,8 @@ void dcd_int_disable(uint8_t rhport) // Receive Set Address request, mcu port must also include status IN response void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - (void) dev_addr; + (void)rhport; + (void)dev_addr; // Respond with status dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0); @@ -437,45 +433,35 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; + (void)rhport; - USB->CNTR |= (uint16_t) USB_CNTR_RESUME; + USB->CNTR |= USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } -static const tusb_desc_endpoint_t ep0OUT_desc = -{ - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = 0x00, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 +static const tusb_desc_endpoint_t ep0OUT_desc = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0x00, + .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, + .bInterval = 0 }; -static const tusb_desc_endpoint_t ep0IN_desc = -{ - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = 0x80, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 +static const tusb_desc_endpoint_t ep0IN_desc = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0x80, + .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, + .bInterval = 0 }; static void dcd_handle_bus_reset(void) { - //__IO uint16_t * const epreg = &(EPREG(0)); USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag - - for(uint32_t i=0; iDADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. } @@ -501,30 +489,63 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) // Verify the CTR_TX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? - if((wEPRegVal & USB_EP_CTR_TX) == 0U) - { + if ((wEPRegVal & USB_EP_CTR_TX) == 0U) { return; } /* clear int flag */ pcd_clear_tx_ep_ctr(USB, EPindex); - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); - if((xfer->total_len != xfer->queued_len)) /* TX not complete */ - { - dcd_transmit_packet(xfer, EPindex); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + + if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + // Ignore spurious interrupts that we don't schedule + // host can send IN token while there is no data to send, since ISO does not have NAK + // this will result to zero length packet --> trigger interrupt (which cannot be masked) + if (!xfer->iso_in_sending) { + return; + } + xfer->iso_in_sending = false; + + if (wEPRegVal & USB_EP_DTOG_TX) { + pcd_set_ep_tx_dbuf0_cnt(USB, EPindex, 0); + } else { + pcd_set_ep_tx_dbuf1_cnt(USB, EPindex, 0); + } } - else /* TX Complete */ - { + + if ((xfer->total_len != xfer->queued_len)) { + dcd_transmit_packet(xfer, EPindex); + } else { dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); } } // Handle CTR interrupt for the RX/OUT direction -// // Upon call, (wIstr & USB_ISTR_DIR) == 0U static void dcd_ep_ctr_rx_handler(uint32_t wIstr) { +#ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata also seems to apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } +#endif + uint32_t EPindex = wIstr & USB_ISTR_EP_ID; uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD; @@ -533,92 +554,83 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? - if((wEPRegVal & USB_EP_CTR_RX) == 0U) - { + if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { return; } - if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */ - { - // The setup_received function uses memcpy, so this must first copy the setup data into - // user memory, to allow for the 32-bit access that memcpy performs. - uint8_t userMemBuf[8]; + if ((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) { + /* Setup packet */ uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex); - /* Get SETUP Packet*/ - if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again. - { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) { // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) - pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); - pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); - dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); - dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); + pcd_set_ep_rx_status(USB, 0u, USB_EP_RX_NAK); + pcd_set_ep_tx_status(USB, 0u, USB_EP_TX_NAK); +#ifdef FSDEV_BUS_32BIT + dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); +#else + // The setup_received function uses memcpy, so this must first copy the setup data into + // user memory, to allow for the 32-bit access that memcpy performs. + uint8_t userMemBuf[8]; + dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB, EPindex), 8); + dcd_event_setup_received(0, (uint8_t *)userMemBuf, true); +#endif } - } - else - { + } else { + // Clear RX CTR interrupt flag + if (ep_addr != 0u) { + pcd_clear_rx_ep_ctr(USB, EPindex); + } + uint32_t count; + uint16_t addr; /* Read from correct register when ISOCHRONOUS (double buffered) */ - if ( (wEPRegVal & USB_EP_DTOG_RX) && ( (wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) ) { - count = pcd_get_ep_tx_cnt(USB, EPindex); + if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + if (wEPRegVal & USB_EP_DTOG_RX) { + count = pcd_get_ep_dbuf0_cnt(USB, EPindex); + addr = pcd_get_ep_dbuf0_address(USB, EPindex); + } else { + count = pcd_get_ep_dbuf1_cnt(USB, EPindex); + addr = pcd_get_ep_dbuf1_address(USB, EPindex); + } } else { count = pcd_get_ep_rx_cnt(USB, EPindex); + addr = pcd_get_ep_rx_address(USB, EPindex); } TU_ASSERT(count <= xfer->max_packet_size, /**/); - // Clear RX CTR interrupt flag - if(ep_addr != 0u) - { - pcd_clear_rx_ep_ctr(USB, EPindex); - } - - if (count != 0U) - { - uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex); - - if (xfer->ff) - { + if (count != 0U) { + if (xfer->ff) { dcd_read_packet_memory_ff(xfer->ff, addr, count); - } - else - { + } else { dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), addr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - /* RX COMPLETE */ + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // all bytes received or short packet dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Though the host could still send, we don't know. - // Does the bulk pipe need to be reset to valid to allow for a ZLP? - } - else - { - uint32_t remaining = (uint32_t)xfer->total_len - (uint32_t)xfer->queued_len; - if(remaining >= xfer->max_packet_size) { - pcd_set_ep_rx_bufsize(USB, EPindex,xfer->max_packet_size); - } else { - pcd_set_ep_rx_bufsize(USB, EPindex,remaining); - } - - if (!((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS)) { - /* Set endpoint active again for receiving more data. - * Note that isochronous endpoints stay active always */ - pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); + } else { + /* Set endpoint active again for receiving more data. + * Note that isochronous endpoints stay active always */ + if ((wEPRegVal & USB_EP_TYPE_MASK) != USB_EP_ISOCHRONOUS) { + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t cnt = tu_min16(remaining, xfer->max_packet_size); + pcd_set_ep_rx_cnt(USB, EPindex, cnt); } + pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); } } // For EP0, prepare to receive another SETUP packet. // Clear CTR last so that a new packet does not overwrite the packing being read. // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared) - if(ep_addr == 0u) - { - // Always be prepared for a status packet... - pcd_set_ep_rx_bufsize(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); + if (ep_addr == 0u) { + // Always be prepared for a status packet... + pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); pcd_clear_rx_ep_ctr(USB, EPindex); } } @@ -628,64 +640,60 @@ static void dcd_ep_ctr_handler(void) uint32_t wIstr; /* stay in loop while pending interrupts */ - while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) - { - - if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */ - { + while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) { + if ((wIstr & USB_ISTR_DIR) == 0U) { + /* TX/IN */ dcd_ep_ctr_tx_handler(wIstr); - } - else /* RX/OUT*/ - { + } else { + /* RX/OUT*/ dcd_ep_ctr_rx_handler(wIstr); } } } -void dcd_int_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) +{ - (void) rhport; + (void)rhport; uint32_t int_status = USB->ISTR; - //const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP - // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; - // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) + // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP + // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; + // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) // The ST driver loops here on the CTR bit, but that loop has been moved into the // dcd_ep_ctr_handler(), so less need to loop here. The other interrupts shouldn't // be triggered repeatedly. /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ - if(int_status & USB_ISTR_SOF) { - clear_istr_bits(USB_ISTR_SOF); + if (int_status & USB_ISTR_SOF) { + USB->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; dcd_event_sof(0, USB->FNR & USB_FNR_FN, true); } - if(int_status & USB_ISTR_RESET) { + if (int_status & USB_ISTR_RESET) { // USBRST is start of reset. - clear_istr_bits(USB_ISTR_RESET); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; dcd_handle_bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } - if (int_status & USB_ISTR_CTR) - { + if (int_status & USB_ISTR_CTR) { /* servicing of the endpoint correct transfer interrupt */ /* clear of the CTR flag into the sub */ dcd_ep_ctr_handler(); } - if (int_status & USB_ISTR_WKUP) - { - reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); - reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); - clear_istr_bits(USB_ISTR_WKUP); + if (int_status & USB_ISTR_WKUP) { + USB->CNTR &= ~USB_CNTR_LPMODE; + USB->CNTR &= ~USB_CNTR_FSUSP; + + USB->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - if (int_status & USB_ISTR_SUSP) - { + if (int_status & USB_ISTR_SUSP) { /* Suspend is asserted for both suspend and unplug events. without Vbus monitoring, * these events cannot be differentiated, so we only trigger suspend. */ @@ -694,20 +702,18 @@ void dcd_int_handler(uint8_t rhport) { USB->CNTR |= USB_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - clear_istr_bits(USB_ISTR_SUSP); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } - if(int_status & USB_ISTR_ESOF) { - if(remoteWakeCountdown == 1u) - { - USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); + if (int_status & USB_ISTR_ESOF) { + if (remoteWakeCountdown == 1u) { + USB->CNTR &= ~USB_CNTR_RESUME; } - if(remoteWakeCountdown > 0u) - { + if (remoteWakeCountdown > 0u) { remoteWakeCountdown--; } - clear_istr_bits(USB_ISTR_ESOF); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } } @@ -717,130 +723,73 @@ void dcd_int_handler(uint8_t rhport) { // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { - (void) rhport; + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; + request->bRequest == TUSB_REQ_SET_ADDRESS) { + uint8_t const dev_addr = (uint8_t)request->wValue; // Setting new address after the whole request is complete - reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); - USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set - } -} - -static void dcd_pma_alloc_reset(void) -{ - open_ep_count = 0; - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) - //TU_LOG2("dcd_pma_alloc_reset()\r\n"); - for(uint32_t i=0; ipma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_ptr = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_ptr = 0U; + USB->DADDR &= ~USB_DADDR_ADD; + USB->DADDR |= dev_addr; // leave the enable bit set } } /*** * Allocate a section of PMA - * - * If the EP number has already been allocated, and the new allocation - * is larger than the old allocation, then this will fail with a TU_ASSERT. - * (This is done to simplify the code. More complicated algorithms could be used) - * + * In case of double buffering, high 16bit is the address of 2nd buffer * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) +static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf) { - xfer_ctl_t* epXferCtl = xfer_ctl_ptr(ep_addr); - - if(epXferCtl->pma_alloc_size != 0U) - { - //TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr); - // Previously allocated - TU_ASSERT(length <= epXferCtl->pma_alloc_size, 0xFFFF); // Verify no larger than previous alloc - return epXferCtl->pma_ptr; - } - - open_ep_count++; + // Ensure allocated buffer is aligned +#ifdef FSDEV_BUS_32BIT + length = (length + 3) & ~0x03; +#else + length = (length + 1) & ~0x01; +#endif - uint16_t addr = ep_buf_ptr; + uint32_t addr = ep_buf_ptr; ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer - // Verify no overflow - TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF); + if (dbuf) { + addr |= ((uint32_t)ep_buf_ptr) << 16; + ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer + } - epXferCtl->pma_ptr = addr; - epXferCtl->pma_alloc_size = length; - //TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr); + // Verify packet buffer is not overflowed + TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF); return addr; } -/*** - * Free a block of PMA space - */ -static void dcd_pma_free(uint8_t ep_addr) -{ - // Presently, this should never be called for EP0 IN/OUT - TU_ASSERT(open_ep_count > 2, /**/); - TU_ASSERT(xfer_ctl_ptr(ep_addr)->max_packet_size != 0, /**/); - open_ep_count--; - - // If count is 2, only EP0 should be open, so allocations can be mostly reset. - - if(open_ep_count == 2) - { - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT + 2*CFG_TUD_ENDPOINT0_SIZE; // 8 bytes per endpoint (two TX and two RX words, each), and EP0 - - // Skip EP0 - for(uint32_t i=1; ipma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_ptr = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_ptr = 0U; - } - } -} - /*** * Allocate hardware endpoint */ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) { uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - for(uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) - { + for (uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) { // Check if already allocated - if(ep_alloc_status[i].allocated[dir] && - ep_alloc_status[i].ep_type == ep_type && - ep_alloc_status[i].ep_num == epnum) - { + if (ep_alloc_status[i].allocated[dir] && + ep_alloc_status[i].ep_type == ep_type && + ep_alloc_status[i].ep_num == epnum) { return i; } // If EP of current direction is not allocated // Except for ISO endpoint, both direction should be free - if(!ep_alloc_status[i].allocated[dir] && - (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) - { + if (!ep_alloc_status[i].allocated[dir] && + (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) { // Check if EP number is the same - if(ep_alloc_status[i].ep_num == 0xFF || - ep_alloc_status[i].ep_num == epnum) - { + if (ep_alloc_status[i].ep_num == 0xFF || ep_alloc_status[i].ep_num == epnum) { // One EP pair has to be the same type - if(ep_alloc_status[i].ep_type == 0xFF || - ep_alloc_status[i].ep_type == ep_type) - { + if (ep_alloc_status[i].ep_type == 0xFF || ep_alloc_status[i].ep_type == ep_type) { ep_alloc_status[i].ep_num = epnum; ep_alloc_status[i].ep_type = ep_type; ep_alloc_status[i].allocated[dir] = true; @@ -855,121 +804,79 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) TU_ASSERT(0); } -/*** - * Free hardware endpoint - */ -static void dcd_ep_free(uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - for(uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) - { - // Check if EP number & dir are the same - if(ep_alloc_status[i].ep_num == epnum && - ep_alloc_status[i].allocated[dir] == dir) - { - ep_alloc_status[i].allocated[dir] = false; - // Reset entry if ISO endpoint or both direction are free - if(ep_alloc_status[i].ep_type == TUSB_XFER_ISOCHRONOUS || - !ep_alloc_status[i].allocated[dir ^ 1]) - { - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; - - return; - } - } - } -} - // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) { (void)rhport; - uint8_t const ep_idx = dcd_ep_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->bmAttributes.xfer); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; + uint8_t const ep_idx = dcd_ep_alloc(ep_addr, p_endpoint_desc->bmAttributes.xfer); + uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); uint16_t pma_addr; uint32_t wType; TU_ASSERT(ep_idx < STFSDEV_EP_COUNT); - TU_ASSERT(buffer_size <= 1024); + TU_ASSERT(buffer_size <= 64); // Set type - switch(p_endpoint_desc->bmAttributes.xfer) { - case TUSB_XFER_CONTROL: - wType = USB_EP_CONTROL; - break; - case TUSB_XFER_ISOCHRONOUS: - wType = USB_EP_ISOCHRONOUS; - break; - case TUSB_XFER_BULK: - wType = USB_EP_CONTROL; - break; - - case TUSB_XFER_INTERRUPT: - wType = USB_EP_INTERRUPT; - break; - - default: - TU_ASSERT(false); + switch (p_endpoint_desc->bmAttributes.xfer) { + case TUSB_XFER_CONTROL: + wType = USB_EP_CONTROL; + break; + case TUSB_XFER_BULK: + wType = USB_EP_CONTROL; + break; + + case TUSB_XFER_INTERRUPT: + wType = USB_EP_INTERRUPT; + break; + + default: + // Note: ISO endpoint should use alloc / active functions + TU_ASSERT(false); } pcd_set_eptype(USB, ep_idx, wType); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(p_endpoint_desc->bEndpointAddress)); - // Be normal, for now, instead of only accepting zero-byte packets (on control endpoint) - // or being double-buffered (bulk endpoints) - pcd_clear_ep_kind(USB,0); + pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - /* Create a packet memory buffer area. For isochronous endpoints, - * use the same buffer as the double buffer, essentially disabling double buffering */ - pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, buffer_size); + /* Create a packet memory buffer area. */ + pma_addr = dcd_pma_alloc(buffer_size, false); - if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) ) - { - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; - pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size); + if (dir == TUSB_DIR_IN) { + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); pcd_clear_tx_dtog(USB, ep_idx); - } - - if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) ) - { - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; - pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size); + } else { + pcd_set_ep_rx_address(USB, ep_idx, pma_addr); + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); pcd_clear_rx_dtog(USB, ep_idx); } - /* Enable endpoint */ - if (dir == TUSB_DIR_IN) - { - if(wType == USB_EP_ISOCHRONOUS) { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } else { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); - } - } else - { - if(wType == USB_EP_ISOCHRONOUS) { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - } else { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); - } - } - - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->max_packet_size = packet_size; - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->ep_idx = ep_idx; + xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; + xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; return true; } -void dcd_edpt_close_all (uint8_t rhport) +void dcd_edpt_close_all(uint8_t rhport) { - (void) rhport; - // TODO implement dcd_edpt_close_all() + (void)rhport; + + for (uint32_t i = 1; i < STFSDEV_EP_COUNT; i++) { + // Reset endpoint + pcd_set_endpoint(USB, i, 0); + // Clear EP allocation status + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].allocated[0] = false; + ep_alloc_status[i].allocated[1] = false; + } + + // Reset PMA allocation + ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * MAX_EP_COUNT + 2 * CFG_TUD_ENDPOINT0_SIZE; } /** @@ -979,223 +886,203 @@ void dcd_edpt_close_all (uint8_t rhport) * * This also clears transfers in progress, should there be any. */ -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if(dir == TUSB_DIR_IN) - { + if (dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } - else - { + } else { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); } - - dcd_ep_free(ep_addr); - - dcd_pma_free(ep_addr); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; - TU_ASSERT(largest_packet_size <= 1024); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); const uint16_t buffer_size = pcd_aligned_buffer_size(largest_packet_size); - /* Create a packet memory buffer area. For isochronous endpoints, - * use the same buffer as the double buffer, essentially disabling double buffering */ - uint16_t pma_addr = dcd_pma_alloc(ep_addr, buffer_size); - - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, + for smaller devices double buffering occupy too much space. */ +#if FSDEV_PMA_SIZE > 1024u + uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); + uint16_t pma_addr2 = pma_addr >> 16; +#else + uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); + uint16_t pma_addr2 = pma_addr; +#endif + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + pcd_set_ep_rx_address(USB, ep_idx, pma_addr2); pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; + xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; return true; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) { (void)rhport; - uint8_t const ep_idx = xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->ep_idx; - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; + uint8_t const ep_idx = xfer_ctl_ptr(ep_addr)->ep_idx; + uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); - const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); - /* Disable endpoint */ - if(dir == TUSB_DIR_IN) - { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } - else - { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - } + pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(p_endpoint_desc->bEndpointAddress)); - // Be normal, for now, instead of only accepting zero-byte packets (on control endpoint) - // or being double-buffered (bulk endpoints) - pcd_clear_ep_kind(USB,0); + pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size); - pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size); pcd_clear_tx_dtog(USB, ep_idx); pcd_clear_rx_dtog(USB, ep_idx); - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->max_packet_size = packet_size; + if (dir == TUSB_DIR_IN) { + pcd_rx_dtog(USB, ep_idx); + } else { + pcd_tx_dtog(USB, ep_idx); + } + + xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; return true; } // Currently, single-buffered, and only 64 bytes at a time (max) -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - - if(len > xfer->max_packet_size) // max packet size for FS transfer - { + if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix); - uint16_t addr_ptr = *pcd_ep_tx_address_ptr(USB,ep_ix); + bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + uint16_t addr_ptr; - if (xfer->ff) - { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); - } - else - { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + if (is_iso) { + if (ep_reg & USB_EP_DTOG_TX) { + addr_ptr = pcd_get_ep_dbuf1_address(USB, ep_ix); + pcd_set_ep_tx_dbuf1_cnt(USB, ep_ix, len); + } else { + addr_ptr = pcd_get_ep_dbuf0_address(USB, ep_ix); + pcd_set_ep_tx_dbuf0_cnt(USB, ep_ix, len); + } + } else { + addr_ptr = pcd_get_ep_tx_address(USB, ep_ix); + pcd_set_ep_tx_cnt(USB, ep_ix, len); } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - /* Write into correct register when ISOCHRONOUS (double buffered) */ - if ( (ep_reg & USB_EP_DTOG_TX) && ( (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) ) { - pcd_set_ep_rx_cnt(USB, ep_ix, len); + if (xfer->ff) { + dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); } else { - pcd_set_ep_tx_cnt(USB, ep_ix, len); + dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + dcd_int_disable(0); pcd_set_ep_tx_status(USB, ep_ix, USB_EP_TX_VALID); + if (is_iso) { + xfer->iso_in_sending = true; + } + dcd_int_enable(0); } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - - if ( dir == TUSB_DIR_OUT ) - { + if (dir == TUSB_DIR_IN) { + dcd_transmit_packet(xfer, ep_idx); + } else { // A setup token can occur immediately after an OUT STATUS packet so make sure we have a valid // buffer for the control endpoint. - if (ep_idx == 0 && buffer == NULL) - { - xfer->buffer = (uint8_t*)_setup_packet; + if (ep_idx == 0 && xfer->buffer == NULL) { + xfer->buffer = (uint8_t *)_setup_packet; } - if(total_bytes > xfer->max_packet_size) - { - pcd_set_ep_rx_bufsize(USB,ep_idx,xfer->max_packet_size); + uint32_t cnt = (uint32_t ) tu_min16(xfer->total_len, xfer->max_packet_size); + uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); + + if ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + pcd_set_ep_rx_dbuf0_cnt(USB, ep_idx, cnt); + pcd_set_ep_rx_dbuf1_cnt(USB, ep_idx, cnt); } else { - pcd_set_ep_rx_bufsize(USB,ep_idx,total_bytes); + pcd_set_ep_rx_cnt(USB, ep_idx, cnt); } + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_VALID); } - else // IN - { - dcd_transmit_packet(xfer,ep_idx); - } + return true; } -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - (void) rhport; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); - uint8_t const epnum = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + return edpt_xfer(rhport, ep_addr); +} + +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) +{ + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); xfer->buffer = NULL; - xfer->ff = ff; + xfer->ff = ff; xfer->total_len = total_bytes; xfer->queued_len = 0; - if ( dir == TUSB_DIR_OUT ) - { - if(total_bytes > xfer->max_packet_size) - { - pcd_set_ep_rx_bufsize(USB,epnum,xfer->max_packet_size); - } else { - pcd_set_ep_rx_bufsize(USB,epnum,total_bytes); - } - pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID); - } - else // IN - { - dcd_transmit_packet(xfer,epnum); - } - return true; + return edpt_xfer(rhport, ep_addr); } -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) - { // IN + if (dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_STALL); - } - else - { // OUT + } else { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_STALL); } } -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) - { // IN - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { + if (dir == TUSB_DIR_IN) { // IN + if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); } /* Reset to DATA0 if clearing stall condition. */ pcd_clear_tx_dtog(USB, ep_idx); - } - else - { // OUT - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { + } else { // OUT + if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); } /* Reset to DATA0 if clearing stall condition. */ @@ -1203,89 +1090,144 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) } } +#ifdef FSDEV_BUS_32BIT +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) +{ + const uint8_t *srcVal = src; + volatile uint32_t *dst32 = (volatile uint32_t *)(USB_PMAADDR + dst); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + *dst32++ = tu_unaligned_read32(srcVal); + srcVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) { + uint32_t wrVal = *srcVal; + wNBytes--; + + if (wNBytes) { + wrVal |= *++srcVal << 8; + wNBytes--; + + if (wNBytes) { + wrVal |= *++srcVal << 16; + } + } + + *dst32 = wrVal; + } + + return true; +} +#else // Packet buffer access can only be 8- or 16-bit. /** - * @brief Copy a buffer from user memory area to packet memory area (PMA). - * This uses byte-access for user memory (so support non-aligned buffers) - * and 16-bit access for packet memory. - * @param dst, byte address in PMA; must be 16-bit aligned - * @param src pointer to user memory area. - * @param wPMABufAddr address into PMA. - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) + * @brief Copy a buffer from user memory area to packet memory area (PMA). + * This uses byte-access for user memory (so support non-aligned buffers) + * and 16-bit access for packet memory. + * @param dst, byte address in PMA; must be 16-bit aligned + * @param src pointer to user memory area. + * @param wPMABufAddr address into PMA. + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; uint16_t temp1, temp2; - const uint8_t * srcVal; + const uint8_t *srcVal; // The GCC optimizer will combine access to 32-bit sizes if we let it. Force // it volatile so that it won't do that. __IO uint16_t *pdwVal; srcVal = src; - pdwVal = &pma[PMA_STRIDE*(dst>>1)]; + pdwVal = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; - while (n--) - { + while (n--) { temp1 = (uint16_t)*srcVal; srcVal++; - temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)) ; + temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)); *pdwVal = temp2; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; srcVal++; } - if (wNBytes & 0x01) - { + if (wNBytes) { temp1 = *srcVal; *pdwVal = temp1; } return true; } +#endif /** - * @brief Copy from FIFO to packet memory area (PMA). - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes) + * @brief Copy from FIFO to packet memory area (PMA). + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); + uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (dst aligned to 16 bit) - if((cnt_lin & 0x01) && cnt_wrap) - { + // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit) +#ifdef FSDEV_BUS_32BIT + if ((cnt_lin & 0x03) && cnt_wrap) { // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin &~0x01); - dst += cnt_lin &~0x01; + dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x03); + dst += cnt_lin & ~0x03; + + // Copy last linear bytes & first wrapped bytes to buffer + uint32_t i; + uint8_t tmp[4]; + for (i = 0; i < (cnt_lin & 0x03); i++) { + tmp[i] = ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) { + tmp[i] = *(uint8_t *)info.ptr_wrap; + info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; + } + + // Write unaligned buffer + dcd_write_packet_memory(dst, &tmp, 4); + dst += 4; + + // Copy rest of wrapped byte + if (wCnt) + dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); + } +#else + if ((cnt_lin & 0x01) && cnt_wrap) { + // Copy first linear part + dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x01); + dst += cnt_lin & ~0x01; // Copy last linear byte & first wrapped byte - uint16_t tmp = ((uint8_t*)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t*)info.ptr_wrap)[0]) << 8U); + uint16_t tmp = ((uint8_t *)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t *)info.ptr_wrap)[0]) << 8U); dcd_write_packet_memory(dst, &tmp, 2); dst += 2; // Copy rest of wrapped byte - dcd_write_packet_memory(dst, ((uint8_t*)info.ptr_wrap) + 1, cnt_wrap - 1); + dcd_write_packet_memory(dst, ((uint8_t *)info.ptr_wrap) + 1, cnt_wrap - 1); } - else - { +#endif + else { // Copy linear part dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin); dst += info.len_lin; - if(info.len_wrap) - { + if (info.len_wrap) { // Copy wrapped byte dcd_write_packet_memory(dst, info.ptr_wrap, cnt_wrap); } @@ -1296,13 +1238,44 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN return true; } +#ifdef FSDEV_BUS_32BIT +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) +{ + uint8_t *dstVal = dst; + volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + tu_unaligned_write32(dstVal, *src32++); + dstVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) { + uint32_t rdVal = *src32; + + *dstVal = tu_u32_byte0(rdVal); + wNBytes--; + + if (wNBytes) { + *++dstVal = tu_u32_byte1(rdVal); + wNBytes--; + + if (wNBytes) { + *++dstVal = tu_u32_byte2(rdVal); + } + } + } + + return true; +} +#else /** - * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes) + * @brief Copy a buffer from packet memory area (PMA) to user memory area. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; // The GCC optimizer will combine access to 32-bit sizes if we let it. Force @@ -1310,70 +1283,93 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN __IO const uint16_t *pdwVal; uint32_t temp; - pdwVal = &pma[PMA_STRIDE*(src>>1)]; - uint8_t *dstVal = (uint8_t*)dst; + pdwVal = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; + uint8_t *dstVal = (uint8_t *)dst; - while (n--) - { + while (n--) { temp = *pdwVal; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; *dstVal++ = ((temp >> 0) & 0xFF); *dstVal++ = ((temp >> 8) & 0xFF); } - if (wNBytes & 0x01) - { + if (wNBytes & 0x01) { temp = *pdwVal; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; *dstVal++ = ((temp >> 0) & 0xFF); } return true; } +#endif /** - * @brief Copy a buffer from user packet memory area (PMA) to FIFO. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes) + * @brief Copy a buffer from user packet memory area (PMA) to FIFO. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO + tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); + uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); // We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (src aligned to 16 bit) - if((cnt_lin & 0x01) && cnt_wrap) - { + // To ensure PMA is always access aligned (src aligned to 16 or 32 bit) +#ifdef FSDEV_BUS_32BIT + if ((cnt_lin & 0x03) && cnt_wrap) { // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin &~0x01); - src += cnt_lin &~0x01; + dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x03); + src += cnt_lin & ~0x03; - // Copy last linear byte & first wrapped byte - uint16_t tmp; - dcd_read_packet_memory(&tmp, src, 2); + // Copy last linear bytes & first wrapped bytes + uint8_t tmp[4]; + dcd_read_packet_memory(tmp, src, 4); + src += 4; + + uint32_t i; + for (i = 0; i < (cnt_lin & 0x03); i++) { + ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i] = tmp[i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) { + *(uint8_t *)info.ptr_wrap = tmp[i]; + info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; + } - ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = (uint8_t)tmp; - ((uint8_t*)info.ptr_wrap)[0] = (uint8_t)(tmp >> 8U); + // Copy rest of wrapped byte + if (wCnt) + dcd_read_packet_memory(info.ptr_wrap, src, wCnt); + } +#else + if ((cnt_lin & 0x01) && cnt_wrap) { + // Copy first linear part + dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x01); + src += cnt_lin & ~0x01; + + // Copy last linear byte & first wrapped byte + uint8_t tmp[2]; + dcd_read_packet_memory(tmp, src, 2); src += 2; + ((uint8_t *)info.ptr_lin)[cnt_lin - 1] = tmp[0]; + ((uint8_t *)info.ptr_wrap)[0] = tmp[1]; + // Copy rest of wrapped byte - dcd_read_packet_memory(((uint8_t*)info.ptr_wrap) + 1, src, cnt_wrap - 1); + dcd_read_packet_memory(((uint8_t *)info.ptr_wrap) + 1, src, cnt_wrap - 1); } - else - { +#endif + else { // Copy linear part dcd_read_packet_memory(info.ptr_lin, src, cnt_lin); src += cnt_lin; - if(info.len_wrap) - { + if (info.len_wrap) { // Copy wrapped byte dcd_read_packet_memory(info.ptr_wrap, src, cnt_wrap); } diff --git a/test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h similarity index 53% rename from test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h rename to test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h index e3fc8aeb..7992f34a 100644 --- a/test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/test-devices/composite-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h @@ -1,34 +1,36 @@ -/** - * Copyright(c) 2016 STMicroelectronics - * Copyright(c) N Conrad - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ +/* + * Copyright(c) 2016 STMicroelectronics + * Copyright(c) N Conrad + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the TinyUSB stack. + */ // This file contains source copied from ST's HAL, and thus should have their copyright statement. -// PMA_LENGTH is PMA buffer size in bytes. +// FSDEV_PMA_SIZE is PMA buffer size in bytes. // On 512-byte devices, access with a stride of two words (use every other 16-bit address) // On 1024-byte devices, access with a stride of one word (use every 16-bit address) @@ -37,7 +39,7 @@ #if CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) // F0x2 models are crystal-less // All have internal D+ pull-up // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support @@ -45,7 +47,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word @@ -56,7 +58,7 @@ defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) #include "stm32f3xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) @@ -65,37 +67,98 @@ defined(STM32F302xD) || defined(STM32F302xE) || \ defined(STM32F303xD) || defined(STM32F303xE) #include "stm32f3xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support // When CAN clock is enabled, USB can use first 768 bytes ONLY. #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 #include "stm32l1xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) #elif CFG_TUSB_MCU == OPT_MCU_STM32G4 #include "stm32g4xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + #include "stm32h5xx.h" + #define FSDEV_BUS_32BIT + + #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) + #define USB_DRD_BASE USB_DRD_FS_BASE + #endif + + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) /* ST provided header has incorrect value */ #undef USB_PMAADDR #define USB_PMAADDR USB1_PMAADDR #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 #include "stm32l5xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #ifndef USB_PMAADDR #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) @@ -107,25 +170,41 @@ #endif // For purposes of accessing the packet -#if ((PMA_LENGTH) == 512u) - #define PMA_STRIDE (2u) -#elif ((PMA_LENGTH) == 1024u) - #define PMA_STRIDE (1u) +#if ((FSDEV_PMA_SIZE) == 512u) + #define FSDEV_PMA_STRIDE (2u) +#elif ((FSDEV_PMA_SIZE) == 1024u) + #define FSDEV_PMA_STRIDE (1u) #endif -// And for type-safety create a new macro for the volatile address of PMAADDR +// The fsdev_bus_t type can be used for both register and PMA access necessities +// For type-safety create a new macro for the volatile address of PMAADDR // The compiler should warn us if we cast it to a non-volatile type? +#ifdef FSDEV_BUS_32BIT +typedef uint32_t fsdev_bus_t; +static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; + +#else +typedef uint16_t fsdev_bus_t; // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; -// prototypes -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue); +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { + size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; + total_word_offset *= FSDEV_PMA_STRIDE; + return &(pma[total_word_offset]); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +} +#endif /* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) { /* The STM32 full speed USB peripheral supports only a limited set of * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ uint16_t blocksize = (size > 62) ? 32 : 2; @@ -136,21 +215,28 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si return numblocks * blocksize; } -/* SetENDPOINT */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); + *reg = wRegValue; +#else __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u); *reg = (uint16_t)wRegValue; +#endif } -/* GetENDPOINT */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); +#else __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u); +#endif return *reg; } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= (uint32_t)USB_EP_T_MASK; regVal |= wType; @@ -158,20 +244,19 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EP_T_FIELD; return regVal; } + /** * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. * @param USBx USB peripheral instance register address. * @param bEpIdx Endpoint Number. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal &= ~USB_EP_CTR_RX; @@ -179,51 +264,42 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal &= ~USB_EP_CTR_TX; regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) pcd_set_endpoint(USBx, bEpIdx,regVal); } + /** * @brief gets counter of the tx buffer. * @param USBx USB peripheral instance register address. * @param bEpIdx Endpoint Number. * @retval Counter value */ -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; +#else __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; +#endif } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; +#else __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; +#endif } -/** - * @brief Sets counter of rx buffer with no. of blocks. - * @param dwReg Register - * @param wCount Counter. - * @param wNBlocks no. of Blocks. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwReg, size_t wCount) -{ - /* We assume that the buffer size is already aligned to hardware requirements. */ - uint16_t blocksize = (wCount > 62) ? 1 : 0; - uint16_t numblocks = wCount / (blocksize ? 32 : 2); - - /* There should be no remainder in the above calculation */ - TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); -} +#define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt +#define pcd_get_ep_dbuf1_cnt pcd_get_ep_rx_cnt /** * @brief Sets address in an endpoint register. @@ -232,8 +308,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwRe * @param bAddr Address. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= bAddr; @@ -241,59 +316,106 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) -{ - size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; - total_word_offset *= PMA_STRIDE; - return &(pma[total_word_offset]); +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx] & 0x0000FFFFu ; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); +#endif } -// Pointers to the PMA table entries (using the ARM address space) -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); -} -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx + 1] & 0x0000FFFFu; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#endif } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#define pcd_get_ep_dbuf0_address pcd_get_ep_tx_address +#define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; +#endif } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ +#define pcd_set_ep_dbuf0_address pcd_set_ep_tx_address +#define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ +#define pcd_set_ep_tx_dbuf0_cnt pcd_set_ep_tx_cnt + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else __IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ - __IO uint16_t *pdwReg = pcd_ep_tx_cnt_ptr((USBx),(bEpIdx)); - wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, wCount); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, + uint32_t blocksize, uint32_t numblocks) { + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); +#else + __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); + *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ - __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpIdx)); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, wCount); + + /* We assume that the buffer size is already aligned to hardware requirements. */ + uint16_t blocksize = (wCount > 62) ? 1 : 0; + uint16_t numblocks = wCount / (blocksize ? 32 : 2); + + /* There should be no remainder in the above calculation */ + TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_dbuf0_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount); } +#define pcd_set_ep_rx_dbuf1_cnt pcd_set_ep_rx_cnt + /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. @@ -301,8 +423,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USB * @param wState new state * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPTX_DTOGMASK; @@ -319,7 +440,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); -} /* pcd_set_ep_tx_status */ +} /** * @brief sets the status for rx transfer (bits STAT_TX[1:0]) @@ -329,31 +450,27 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPRX_DTOGMASK; /* toggle first bit ? */ - if((USB_EPRX_DTOG1 & wState)!= 0U) - { + if((USB_EPRX_DTOG1 & wState)!= 0U) { regVal ^= USB_EPRX_DTOG1; } /* toggle second bit ? */ - if((USB_EPRX_DTOG2 & wState)!= 0U) - { + if((USB_EPRX_DTOG2 & wState)!= 0U) { regVal ^= USB_EPRX_DTOG2; } regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); -} /* pcd_set_ep_rx_status */ +} -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); return (regVal & USB_EPRX_STAT) >> (12u); -} /* pcd_get_ep_rx_status */ +} /** @@ -362,16 +479,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * * @param bEpIdx Endpoint Number. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; @@ -384,21 +499,16 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32 * @param bEpIdx Endpoint Number. * @retval None */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_RX) != 0) - { + if((regVal & USB_EP_DTOG_RX) != 0) { pcd_rx_dtog(USBx,bEpIdx); } } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_TX) != 0) - { + if((regVal & USB_EP_DTOG_TX) != 0) { pcd_tx_dtog(USBx,bEpIdx); } } @@ -409,17 +519,15 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, * @param bEpIdx Endpoint Number. * @retval None */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal |= USB_EP_KIND; regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) -{ + +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPKIND_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dcd_dwc2.c b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c similarity index 61% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dcd_dwc2.c rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c index 22c82201..692096fc 100644 --- a/test-devices/composite-stm32/lib/tinyusb/dwc2/dcd_dwc2.c +++ b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c @@ -82,8 +82,8 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { - uint8_t * buffer; - tu_fifo_t * ff; + uint8_t* buffer; + tu_fifo_t* ff; uint16_t total_len; uint16_t max_size; uint8_t interval; @@ -93,45 +93,182 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) // EP0 transfers are limited to 1 packet - larger sizes has to be split -static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type // TX FIFO RAM allocation so far in words - RX FIFO size is readily available from dwc2->grxfsiz -static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) -static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) +static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by static bool _sof_en; -// Calculate the RX FIFO size according to recommendations from reference manual -static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count) -{ - return 15 + 2*(max_ep_size/4) + 2*ep_count; +// Calculate the RX FIFO size according to minimum recommendations from reference manual +// RxFIFO = (5 * number of control endpoints + 8) + +// ((largest USB packet used / 4) + 1 for status information) + +// (2 * number of OUT endpoints) + 1 for Global NAK +// with number of control endpoints = 1 we have +// RxFIFO = 15 + (largest USB packet used / 4) + 2 * number of OUT endpoints +// we double the largest USB packet size to be able to hold up to 2 packets +static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count) { + return 15 + 2 * (max_ep_size / 4) + 2 * ep_count; } -static void update_grxfsiz(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +TU_ATTR_ALWAYS_INLINE static inline void fifo_flush_tx(dwc2_regs_t* dwc2, uint8_t epnum) { + // flush TX fifo and wait for it cleared + dwc2->grstctl = GRSTCTL_TXFFLSH | (epnum << GRSTCTL_TXFNUM_Pos); + while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {} +} +TU_ATTR_ALWAYS_INLINE static inline void fifo_flush_rx(dwc2_regs_t* dwc2) { + // flush RX fifo and wait for it cleared + dwc2->grstctl = GRSTCTL_RXFFLSH; + while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {} +} + +static bool fifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_ASSERT(epnum < ep_count); + + uint16_t fifo_size = tu_div_ceil(packet_size, 4); + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // In FIFO is allocated by following rules: + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + if (dir == TUSB_DIR_OUT) { + // Calculate required size of RX FIFO + uint16_t const sz = calc_grxfsiz(4 * fifo_size, ep_count); + + // If size_rx needs to be extended check if possible and if so enlarge it + if (dwc2->grxfsiz < sz) { + TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size / 4); - // Determine largest EP size for RX FIFO - uint16_t max_epsize = 0; - for (uint8_t epnum = 0; epnum < ep_count; epnum++) - { - max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size); + // Enlarge RX FIFO + dwc2->grxfsiz = sz; + } + } else { + // Note if The TXFELVL is configured as half empty. In order + // to be able to write a packet at that point, the fifo must be twice the max_size. + if ((dwc2->gahbcfg & GAHBCFG_TXFELVL) == 0) { + fifo_size *= 2; + } + + // Check if free space is available + TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size / 4); + _allocated_fifo_words_tx += fifo_size; + TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %" PRIu32, fifo_size * 4, + _dwc2_controller[rhport].ep_fifo_size - _allocated_fifo_words_tx * 4); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | + (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx); } - // Update size of RX FIFO - dwc2->grxfsiz = calc_grxfsiz(max_epsize, ep_count); + return true; +} + +static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); + xfer->interval = p_endpoint_desc->bInterval; + + // USBAEP, EPTYP, SD0PID_SEVNFRM, MPSIZ are the same for IN and OUT endpoints. + uint32_t const dxepctl = (1 << DOEPCTL_USBAEP_Pos) | + (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | + (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DOEPCTL_MPSIZ_Pos); + + if (dir == TUSB_DIR_OUT) { + dwc2->epout[epnum].doepctl = dxepctl; + dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); + } else { + dwc2->epin[epnum].diepctl = dxepctl | (epnum << DIEPCTL_TXFNUM_Pos); + dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum)); + } +} + +static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { + (void) rhport; + + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + dwc2_epin_t* epin = dwc2->epin; + + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA)) { + epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + } else { + // Stop transmitting packets and NAK IN xfers. + epin[epnum].diepctl |= DIEPCTL_SNAK; + while ((epin[epnum].diepint & DIEPINT_INEPNE) == 0) {} + + // Disable the endpoint. + epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + while ((epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0) {} + + epin[epnum].diepint = DIEPINT_EPDISD; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + fifo_flush_tx(dwc2, epnum); + } else { + dwc2_epout_t* epout = dwc2->epout; + + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA)) { + epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + dwc2->dctl |= DCTL_SGONAK; + while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} + + // Ditto here- disable the endpoint. + epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + while ((epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0) {} + + epout[epnum].doepint = DOEPINT_EPDISD; + + // Allow other OUT endpoints to keep receiving. + dwc2->dctl |= DCTL_CGONAK; + } + } } // Start of Bus Reset -static void bus_reset(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void bus_reset(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; tu_memclr(xfer_status, sizeof(xfer_status)); - _out_ep_closed = false; _sof_en = false; @@ -139,15 +276,24 @@ static void bus_reset(uint8_t rhport) dwc2->dcfg &= ~DCFG_DAD_Msk; // 1. NAK for all OUT endpoints - for ( uint8_t n = 0; n < ep_count; n++ ) - { + for (uint8_t n = 0; n < ep_count; n++) { dwc2->epout[n].doepctl |= DOEPCTL_SNAK; } - // 2. Set up interrupt mask + // 2. Disable all IN endpoints + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { + dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + } + } + + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); + + // 3. Set up interrupt mask dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); - dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; - dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; + dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; + dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture @@ -206,36 +352,34 @@ static void bus_reset(uint8_t rhport) _allocated_fifo_words_tx = 16; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx); + dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx); // Fixed control EP0 size to 64 bytes dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN ].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; } -static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) -{ +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, + uint16_t total_bytes) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // EP0 is limited to one packet each xfer // We use multiple transaction of xfer->max_size length to get a whole transfer done - if ( epnum == 0 ) - { - xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, dir); + if (epnum == 0) { + xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir); total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); ep0_pending[dir] -= total_bytes; } // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - if ( dir == TUSB_DIR_IN ) - { + if (dir == TUSB_DIR_IN) { dwc2_epin_t* epin = dwc2->epin; // A full IN transfer (multiple packets, possibly) triggers XFRC. @@ -245,20 +389,16 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; // For ISO endpoint set correct odd/even bit for next frame. - if ( (epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1 ) - { + if ((epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); } // Enable fifo empty interrupt only if there are something to put in the fifo. - if ( total_bytes != 0 ) - { + if (total_bytes != 0) { dwc2->diepempmsk |= (1 << epnum); } - } - else - { + } else { dwc2_epout_t* epout = dwc2->epout; // A full OUT transfer (multiple packets, possibly) triggers XFRC. @@ -267,9 +407,8 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c ((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk); epout[epnum].doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; - if ( (epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && - XFER_CTL_BASE(epnum, dir)->interval == 1 ) - { + if ((epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && + XFER_CTL_BASE(epnum, dir)->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); epout[epnum].doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); @@ -281,103 +420,46 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c /* Controller API *------------------------------------------------------------------*/ #if CFG_TUSB_DEBUG >= DWC2_DEBUG -void print_dwc2_info(dwc2_regs_t * dwc2) -{ - dwc2_ghwcfg2_t const * hw_cfg2 = &dwc2->ghwcfg2_bm; - dwc2_ghwcfg3_t const * hw_cfg3 = &dwc2->ghwcfg3_bm; - dwc2_ghwcfg4_t const * hw_cfg4 = &dwc2->ghwcfg4_bm; - -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); - TU_LOG_HEX(DWC2_DEBUG, dwc2->guid); - TU_LOG_HEX(DWC2_DEBUG, dwc2->gsnpsid); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg1); - - // HW configure 2 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg2); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->op_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->arch ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->point2point ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->hs_phy_type ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->fs_phy_type ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_dev_ep ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_host_ch ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->period_channel_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->enable_dynamic_fifo ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->mul_cpu_int ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->nperiod_tx_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->host_period_tx_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->dev_token_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->otg_enable_ic_usb ); - - // HW configure 3 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg3); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->xfer_size_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->packet_size_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->i2c_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->vendor_ctrl_itf ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->optional_feature_removed ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->synch_reset ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_adp_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable_hsic ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->battery_charger_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->lpm_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->total_fifo_size ); - - // HW configure 4 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg4); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_period_in_ep ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->power_optimized ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ahb_freq_min ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->hibernation ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->service_interval_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ipg_isoc_en ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->acg_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->utmi_phy_data_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dev_ctrl_ep_num ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->iddg_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->vbus_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->a_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->b_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dedicated_fifos ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_in_eps ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_desc_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_dynamic ); +void print_dwc2_info(dwc2_regs_t* dwc2) { + // print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 + // use dwc2_info.py/md for bit-field value and comparison with other ports + volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid; + TU_LOG(DWC2_DEBUG, "guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n"); + for (size_t i = 0; i < 5; i++) { + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 ", ", p[i]); + } + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 "\r\n", p[5]); } #endif -static void reset_core(dwc2_regs_t * dwc2) -{ +static void reset_core(dwc2_regs_t* dwc2) { // reset core dwc2->grstctl |= GRSTCTL_CSRST; // wait for reset bit is cleared // TODO version 4.20a should wait for RESET DONE mask - while (dwc2->grstctl & GRSTCTL_CSRST) { } + while (dwc2->grstctl & GRSTCTL_CSRST) {} // wait for AHB master IDLE - while ( !(dwc2->grstctl & GRSTCTL_AHBIDL) ) { } + while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for device mode ? } -static bool phy_hs_supported(dwc2_regs_t * dwc2) -{ - // note: esp32 incorrect report its hs_phy_type as utmi +static bool phy_hs_supported(dwc2_regs_t* dwc2) { + (void) dwc2; + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // note: esp32 incorrect report its hs_phy_type as utmi + return false; +#elif !TUD_OPT_HIGH_SPEED return false; #else - return TUD_OPT_HIGH_SPEED && dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE; + return dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE; #endif } -static void phy_fs_init(dwc2_regs_t * dwc2) -{ +static void phy_fs_init(dwc2_regs_t* dwc2) { TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n"); // Select FS PHY @@ -401,15 +483,13 @@ static void phy_fs_init(dwc2_regs_t * dwc2) dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos); } -static void phy_hs_init(dwc2_regs_t * dwc2) -{ +static void phy_hs_init(dwc2_regs_t* dwc2) { uint32_t gusbcfg = dwc2->gusbcfg; // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; - if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) - { + if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) { TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n"); // Select ULPI @@ -423,8 +503,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2) // Disable FS/LS ULPI gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM); - }else - { + } else { TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n"); // Select UTMI+ with 8-bit interface @@ -465,8 +544,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2) dwc2->dcfg = dcfg; } -static bool check_dwc2(dwc2_regs_t * dwc2) -{ +static bool check_dwc2(dwc2_regs_t* dwc2) { #if CFG_TUSB_DEBUG >= DWC2_DEBUG print_dwc2_info(dwc2); #endif @@ -481,41 +559,35 @@ static bool check_dwc2(dwc2_regs_t * dwc2) return true; } -void dcd_init (uint8_t rhport) -{ +void dcd_init(uint8_t rhport) { // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Check Synopsys ID register, failed if controller clock/power is not enabled - TU_VERIFY(check_dwc2(dwc2), ); - + if (!check_dwc2(dwc2)) return; dcd_disconnect(rhport); // max number of endpoints & total_fifo_size are: // hw_cfg2->num_dev_ep, hw_cfg2->total_fifo_size - if( phy_hs_supported(dwc2) ) - { - // Highspeed - phy_hs_init(dwc2); - }else - { - // core does not support highspeed or hs-phy is not present - phy_fs_init(dwc2); + if (phy_hs_supported(dwc2)) { + phy_hs_init(dwc2); // Highspeed + } else { + phy_fs_init(dwc2); // core does not support highspeed or hs phy is not present } // Restart PHY clock dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); - /* Set HS/FS Timeout Calibration to 7 (max available value). - * The number of PHY clocks that the application programs in - * this field is added to the high/full speed interpacket timeout - * duration in the core to account for any additional delays - * introduced by the PHY. This can be required, because the delay - * introduced by the PHY in generating the linestate condition - * can vary from one PHY to another. - */ + /* Set HS/FS Timeout Calibration to 7 (max available value). + * The number of PHY clocks that the application programs in + * this field is added to the high/full speed interpacket timeout + * duration in the core to account for any additional delays + * introduced by the PHY. This can be required, because the delay + * introduced by the PHY in generating the linestate condition + * can vary from one PHY to another. + */ dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); // Force device mode @@ -528,6 +600,9 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. dwc2->dcfg |= DCFG_NZLSOHSK; + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); + // Clear all interrupts uint32_t int_mask = dwc2->gintsts; dwc2->gintsts |= int_mask; @@ -535,11 +610,12 @@ void dcd_init (uint8_t rhport) dwc2->gotgint |= int_mask; // Required as part of core initialization. - // TODO: How should mode mismatch be handled? It will cause - // the core to stop working/require reset. - dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_MMISM | GINTMSK_RXFLVLM | + dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_RXFLVLM | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; + // Configure TX FIFO empty level for interrupt. Default is complete empty + dwc2->gahbcfg |= GAHBCFG_TXFELVL; + // Enable global interrupt dwc2->gahbcfg |= GAHBCFG_GINT; @@ -554,30 +630,26 @@ void dcd_init (uint8_t rhport) dcd_connect(rhport); } -void dcd_int_enable (uint8_t rhport) -{ +void dcd_int_enable(uint8_t rhport) { dwc2_dcd_int_enable(rhport); } -void dcd_int_disable (uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { dwc2_dcd_int_disable(rhport); } -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); // Response with status after changing device address dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_remote_wakeup(uint8_t rhport) -{ +void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // set remote wakeup dwc2->dctl |= DCTL_RWUSIG; @@ -592,35 +664,29 @@ void dcd_remote_wakeup(uint8_t rhport) dwc2->dctl &= ~DCTL_RWUSIG; } -void dcd_connect(uint8_t rhport) -{ +void dcd_connect(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dctl &= ~DCTL_SDIS; } -void dcd_disconnect(uint8_t rhport) -{ +void dcd_disconnect(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dctl |= DCTL_SDIS; } // Be advised: audio, video and possibly other iso-ep classes use dcd_sof_enable() to enable/disable its corresponding ISR on purpose! -void dcd_sof_enable(uint8_t rhport, bool en) -{ +void dcd_sof_enable(uint8_t rhport, bool en) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); _sof_en = en; - if (en) - { + if (en) { dwc2->gintsts = GINTSTS_SOF; dwc2->gintmsk |= GINTMSK_SOFM; - } - else - { + } else { dwc2->gintmsk &= ~GINTMSK_SOFM; } } @@ -629,140 +695,78 @@ void dcd_sof_enable(uint8_t rhport, bool en) /* DCD Endpoint port *------------------------------------------------------------------*/ -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) -{ - (void) rhport; - - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < ep_count); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - xfer->interval = desc_edpt->bInterval; - - uint16_t const fifo_size = tu_div_ceil(xfer->max_size, 4); - - if(dir == TUSB_DIR_OUT) - { - // Calculate required size of RX FIFO - uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count); - - // If size_rx needs to be extended check if possible and if so enlarge it - if (dwc2->grxfsiz < sz) - { - TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4); - - // Enlarge RX FIFO - dwc2->grxfsiz = sz; - } - - dwc2->epout[epnum].doepctl |= (1 << DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DOEPCTL_MPSIZ_Pos); - - dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); - } - else - { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO 0 | - // --------------- (320 or 1024) - 16 - // | IN FIFO 1 | - // --------------- (320 or 1024) - 16 - x - // | . . . . | - // --------------- (320 or 1024) - 16 - x - y - ... - z - // | IN FIFO MAX | - // --------------- - // | FREE | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // In FIFO is allocated by following rules: - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - // Check if free space is available - TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size/4); - - _allocated_fifo_words_tx += fifo_size; - - TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size*4, _dwc2_controller[rhport].ep_fifo_size-_allocated_fifo_words_tx*4); - - // DIEPTXF starts at FIFO #1. - // Both TXFD and TXSA are in unit of 32-bit words. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx); - - dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) | - (epnum << DIEPCTL_TXFNUM_Pos) | - (desc_edpt->bmAttributes.xfer << DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DIEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DIEPCTL_MPSIZ_Pos); - - dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum)); - } - +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { + TU_ASSERT(fifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt))); + edpt_activate(rhport, desc_edpt); return true; } // Close all non-control endpoints, cancel all pending transfers if any. -void dcd_edpt_close_all (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +void dcd_edpt_close_all(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; // Disable non-control interrupt dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); - for(uint8_t n = 1; n < ep_count; n++) - { + for (uint8_t n = 1; n < ep_count; n++) { // disable OUT endpoint - dwc2->epout[n].doepctl = 0; + if (dwc2->epout[n].doepctl & DOEPCTL_EPENA) { + dwc2->epout[n].doepctl |= DOEPCTL_SNAK | DOEPCTL_EPDIS; + } xfer_status[n][TUSB_DIR_OUT].max_size = 0; // disable IN endpoint - dwc2->epin[n].diepctl = 0; + if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { + dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + } xfer_status[n][TUSB_DIR_IN].max_size = 0; } + // reset allocated fifo OUT + dwc2->grxfsiz = calc_grxfsiz(64, ep_count); // reset allocated fifo IN _allocated_fifo_words_tx = 16; + + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + TU_ASSERT(fifo_alloc(rhport, ep_addr, largest_packet_size)); + return true; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + // Disable EP to clear potential incomplete transfers + edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); + + edpt_activate(rhport, p_endpoint_desc); + + return true; } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; // EP0 can only handle one packet - if(epnum == 0) - { + if (epnum == 0) { ep0_pending[dir] = total_bytes; // Schedule the first transaction for EP0 transfer edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); - } - else - { + } else { uint16_t num_packets = (total_bytes / xfer->max_size); uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if ( (short_packet_size > 0) || (total_bytes == 0) ) num_packets++; + if ((short_packet_size > 0) || (total_bytes == 0)) num_packets++; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -775,24 +779,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; uint16_t num_packets = (total_bytes / xfer->max_size); uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if ( short_packet_size > 0 || (total_bytes == 0) ) num_packets++; + if (short_packet_size > 0 || (total_bytes == 0)) num_packets++; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -800,123 +803,27 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } -static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) -{ - (void) rhport; - - dwc2_regs_t *dwc2 = DWC2_REG(rhport); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if ( dir == TUSB_DIR_IN ) - { - dwc2_epin_t* epin = dwc2->epin; - - // Only disable currently enabled non-control endpoint - if ( (epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA) ) - { - epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); - } - else - { - // Stop transmitting packets and NAK IN xfers. - epin[epnum].diepctl |= DIEPCTL_SNAK; - while ( (epin[epnum].diepint & DIEPINT_INEPNE) == 0 ) {} - - // Disable the endpoint. - epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); - while ( (epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0 ) {} - - epin[epnum].diepint = DIEPINT_EPDISD; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - dwc2->grstctl = ((epnum << GRSTCTL_TXFNUM_Pos) | GRSTCTL_TXFFLSH); - while ( (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) != 0 ) {} - } - else - { - dwc2_epout_t* epout = dwc2->epout; - - // Only disable currently enabled non-control endpoint - if ( (epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA) ) - { - epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; - } - else - { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - dwc2->dctl |= DCTL_SGONAK; - while ( (dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0 ) {} - - // Ditto here- disable the endpoint. - epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); - while ( (epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0 ) {} - - epout[epnum].doepint = DOEPINT_EPDISD; - - // Allow other OUT endpoints to keep receiving. - dwc2->dctl |= DCTL_CGONAK; - } - } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + edpt_disable(rhport, ep_addr, false); } -/** - * Close an endpoint. - */ -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_disable(rhport, ep_addr, false); - - // Update max_size - xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation - - if (dir == TUSB_DIR_IN) - { - uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos; - uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos; - - // For now only the last opened endpoint can be closed without fuss. - TU_ASSERT(fifo_start == _dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx,); - _allocated_fifo_words_tx -= fifo_size; - } - else - { - _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty - } +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + edpt_disable(rhport, ep_addr, true); } -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - dcd_edpt_disable(rhport, ep_addr, true); -} - -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // Clear stall and reset data toggle - if ( dir == TUSB_DIR_IN ) - { + if (dir == TUSB_DIR_IN) { dwc2->epin[epnum].diepctl &= ~DIEPCTL_STALL; dwc2->epin[epnum].diepctl |= DIEPCTL_SD0PID_SEVNFRM; - } - else - { + } else { dwc2->epout[epnum].doepctl &= ~DOEPCTL_STALL; dwc2->epout[epnum].doepctl |= DOEPCTL_SD0PID_SEVNFRM; } @@ -925,70 +832,63 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ // Read a single data packet from receive FIFO -static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len) -{ +static void read_fifo_packet(uint8_t rhport, uint8_t* dst, uint16_t len) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile const uint32_t * rx_fifo = dwc2->fifo[0]; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile const uint32_t* rx_fifo = dwc2->fifo[0]; // Reading full available 32 bit words from fifo uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { tu_unaligned_write32(dst, *rx_fifo); dst += 4; } // Read the remaining 1-3 bytes from fifo uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem != 0 ) - { + if (bytes_rem != 0) { uint32_t const tmp = *rx_fifo; dst[0] = tu_u32_byte0(tmp); - if ( bytes_rem > 1 ) dst[1] = tu_u32_byte1(tmp); - if ( bytes_rem > 2 ) dst[2] = tu_u32_byte2(tmp); + if (bytes_rem > 1) dst[1] = tu_u32_byte1(tmp); + if (bytes_rem > 2) dst[2] = tu_u32_byte2(tmp); } } // Write a single data packet to EPIN FIFO -static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const * src, uint16_t len) -{ +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* src, uint16_t len) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile uint32_t * tx_fifo = dwc2->fifo[fifo_num]; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num]; // Pushing full available 32 bit words to fifo uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { *tx_fifo = tu_unaligned_read32(src); src += 4; } // Write the remaining 1-3 bytes into fifo uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + if (bytes_rem) { uint32_t tmp_word = src[0]; - if ( bytes_rem > 1 ) tmp_word |= (src[1] << 8); - if ( bytes_rem > 2 ) tmp_word |= (src[2] << 16); + if (bytes_rem > 1) tmp_word |= (src[1] << 8); + if (bytes_rem > 2) tmp_word |= (src[2] << 16); *tx_fifo = tmp_word; } } -static void handle_rxflvl_irq(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile uint32_t const * rx_fifo = dwc2->fifo[0]; +static void handle_rxflvl_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile uint32_t const* rx_fifo = dwc2->fifo[0]; // Pop control word off FIFO uint32_t const ctl_word = dwc2->grxstsp; - uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk ) >> GRXSTSP_PKTSTS_Pos; - uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk ) >> GRXSTSP_EPNUM_Pos; - uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk ) >> GRXSTSP_BCNT_Pos; + uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; + uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; + uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; dwc2_epout_t* epout = &dwc2->epout[epnum]; @@ -1003,10 +903,10 @@ static void handle_rxflvl_irq(uint8_t rhport) // TU_LOG(DWC2_DEBUG, " daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint); //#endif - switch ( pktsts ) - { + switch (pktsts) { // Global OUT NAK: do nothing - case GRXSTS_PKTSTS_GLOBALOUTNAK: break; + case GRXSTS_PKTSTS_GLOBALOUTNAK: + break; case GRXSTS_PKTSTS_SETUPRX: // Setup packet received @@ -1015,26 +915,22 @@ static void handle_rxflvl_irq(uint8_t rhport) // only the last one is valid. _setup_packet[0] = (*rx_fifo); _setup_packet[1] = (*rx_fifo); - break; + break; case GRXSTS_PKTSTS_SETUPDONE: // Setup packet done (Interrupt) epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - break; + break; - case GRXSTS_PKTSTS_OUTRX: - { + case GRXSTS_PKTSTS_OUTRX: { // Out packet received - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // Read packet off RxFIFO - if ( xfer->ff ) - { + if (xfer->ff) { // Ring buffer tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt); - } - else - { + } else { // Linear buffer read_fifo_packet(rhport, xfer->buffer, bcnt); @@ -1043,73 +939,64 @@ static void handle_rxflvl_irq(uint8_t rhport) } // Truncate transfer length in case of short packet - if ( bcnt < xfer->max_size ) - { + if (bcnt < xfer->max_size) { xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; - if ( epnum == 0 ) - { + if (epnum == 0) { xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; ep0_pending[TUSB_DIR_OUT] = 0; } } } - break; + break; - // Out packet done (Interrupt) + // Out packet done (Interrupt) case GRXSTS_PKTSTS_OUTDONE: - // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a - // May (or not) be 3.10a specific feature/bug or depending on MCU configuration - // XFRC complete is additionally generated when - // - setup packet is received - // - complete the data stage of control write is complete - if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) - { - uint32_t doepint = epout->doepint; - - if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) - { - // skip this "no-data" transfer complete event - // Note: STPKTRX will be clear later by setup received handler - uint32_t clear_flags = DOEPINT_XFRC; - - if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR; - - epout->doepint = clear_flags; - - // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n"); - } + // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a + // May (or not) be 3.10a specific feature/bug or depending on MCU configuration + // XFRC complete is additionally generated when + // - setup packet is received + // - complete the data stage of control write is complete + if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) { + uint32_t doepint = epout->doepint; + + if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) { + // skip this "no-data" transfer complete event + // Note: STPKTRX will be clear later by setup received handler + uint32_t clear_flags = DOEPINT_XFRC; + + if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR; + + epout->doepint = clear_flags; + + // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n"); } - break; + } + break; default: // Invalid TU_BREAKPOINT(); - break; + break; } } -static void handle_epout_irq (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void handle_epout_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; // DAINT for a given EP clears when DOEPINTx is cleared. // OEPINT will be cleared when DAINT's out bits are cleared. - for ( uint8_t n = 0; n < ep_count; n++ ) - { - if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) ) - { + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n)) { dwc2_epout_t* epout = &dwc2->epout[n]; uint32_t const doepint = epout->doepint; // SETUP packet Setup Phase done. - if ( doepint & DOEPINT_STUP ) - { + if (doepint & DOEPINT_STUP) { uint32_t clear_flag = DOEPINT_STUP; // STPKTRX is only available for version from 3_00a - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) - { + if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) { clear_flag |= DOEPINT_STPKTRX; } @@ -1118,20 +1005,16 @@ static void handle_epout_irq (uint8_t rhport) } // OUT XFER complete - if ( epout->doepint & DOEPINT_XFRC ) - { + if (epout->doepint & DOEPINT_XFRC) { epout->doepint = DOEPINT_XFRC; - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); // EP0 can only handle one packet - if ( (n == 0) && ep0_pending[TUSB_DIR_OUT] ) - { + if ((n == 0) && ep0_pending[TUSB_DIR_OUT]) { // Schedule another packet to be received. edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); - } - else - { + } else { dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } } @@ -1139,40 +1022,32 @@ static void handle_epout_irq (uint8_t rhport) } } -static void handle_epin_irq (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void handle_epin_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - dwc2_epin_t* epin = dwc2->epin; + dwc2_epin_t* epin = dwc2->epin; // DAINT for a given EP clears when DIEPINTx is cleared. // IEPINT will be cleared when DAINT's out bits are cleared. - for ( uint8_t n = 0; n < ep_count; n++ ) - { - if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) ) - { + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) { // IN XFER complete (entire xfer). - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); - if ( epin[n].diepint & DIEPINT_XFRC ) - { + if (epin[n].diepint & DIEPINT_XFRC) { epin[n].diepint = DIEPINT_XFRC; // EP0 can only handle one packet - if ( (n == 0) && ep0_pending[TUSB_DIR_IN] ) - { + if ((n == 0) && ep0_pending[TUSB_DIR_IN]) { // Schedule another packet to be transmitted. edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); - } - else - { + } else { dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } } // XFER FIFO empty - if ( (epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n)) ) - { + if ((epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) { // diepint's TXFE bit is read-only, software cannot clear it. // It will only be cleared by hardware when written bytes is more than // - 64 bytes or @@ -1181,8 +1056,7 @@ static void handle_epin_irq (uint8_t rhport) uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos; // Process every single packet (only whole packets can be written to fifo) - for ( uint16_t i = 0; i < remaining_packets; i++ ) - { + for (uint16_t i = 0; i < remaining_packets; i++) { uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos; // Packet can not be larger than ep max size @@ -1190,16 +1064,13 @@ static void handle_epin_irq (uint8_t rhport) // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current // EP has to be checked if the buffer can take another WHOLE packet - if ( packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2) ) break; + if (packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) break; // Push packet to Tx-FIFO - if ( xfer->ff ) - { - volatile uint32_t *tx_fifo = dwc2->fifo[n]; + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[n]; tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size); - } - else - { + } else { write_fifo_packet(rhport, n, xfer->buffer, packet_size); // Increment pointer to xfer data @@ -1208,8 +1079,7 @@ static void handle_epin_irq (uint8_t rhport) } // Turn off TXFE if all bytes are written. - if ( ((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0 ) - { + if (((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0) { dwc2->diepempmsk &= ~(1 << n); } } @@ -1217,55 +1087,50 @@ static void handle_epin_irq (uint8_t rhport) } } -void dcd_int_handler(uint8_t rhport) -{ - dwc2_regs_t *dwc2 = DWC2_REG(rhport); +void dcd_int_handler(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint32_t const int_mask = dwc2->gintmsk; uint32_t const int_status = dwc2->gintsts & int_mask; - if(int_status & GINTSTS_USBRST) - { + if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; bus_reset(rhport); } - if(int_status & GINTSTS_ENUMDNE) - { + if (int_status & GINTSTS_ENUMDNE) { // ENUMDNE is the end of reset where speed of the link is detected - dwc2->gintsts = GINTSTS_ENUMDNE; tusb_speed_t speed; - switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) - { + switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) { case DSTS_ENUMSPD_HS: speed = TUSB_SPEED_HIGH; - break; + break; case DSTS_ENUMSPD_LS: speed = TUSB_SPEED_LOW; - break; + break; case DSTS_ENUMSPD_FS_HSPHY: case DSTS_ENUMSPD_FS: default: speed = TUSB_SPEED_FULL; - break; + break; } + // TODO must update GUSBCFG_TRDT according to link speed + dcd_event_bus_reset(rhport, speed, true); } - if(int_status & GINTSTS_USBSUSP) - { + if (int_status & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } - if(int_status & GINTSTS_WKUINT) - { + if (int_status & GINTSTS_WKUINT) { dwc2->gintsts = GINTSTS_WKUINT; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } @@ -1273,73 +1138,52 @@ void dcd_int_handler(uint8_t rhport) // TODO check GINTSTS_DISCINT for disconnect detection // if(int_status & GINTSTS_DISCINT) - if(int_status & GINTSTS_OTGINT) - { + if (int_status & GINTSTS_OTGINT) { // OTG INT bit is read-only uint32_t const otg_int = dwc2->gotgint; - if (otg_int & GOTGINT_SEDET) - { + if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } dwc2->gotgint = otg_int; } - if(int_status & GINTSTS_SOF) - { - dwc2->gotgint = GINTSTS_SOF; + if(int_status & GINTSTS_SOF) { + dwc2->gintsts = GINTSTS_SOF; + const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; - if (_sof_en) - { - uint32_t frame = (dwc2->dsts & (DSTS_FNSOF)) >> 8; - dcd_event_sof(rhport, frame, true); - } - else - { - // Disable SOF interrupt if SOF was not explicitly enabled. SOF was used for remote wakeup detection + // Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection + if (!_sof_en) { dwc2->gintmsk &= ~GINTMSK_SOFM; } - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + dcd_event_sof(rhport, frame, true); } // RxFIFO non-empty interrupt handling. - if(int_status & GINTSTS_RXFLVL) - { + if (int_status & GINTSTS_RXFLVL) { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // Loop until all available packets were handled - do - { + do { handle_rxflvl_irq(rhport); } while(dwc2->gintsts & GINTSTS_RXFLVL); - // Manage RX FIFO size - if (_out_ep_closed) - { - update_grxfsiz(rhport); - - // Disable flag - _out_ep_closed = false; - } - dwc2->gintmsk |= GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. - if(int_status & GINTSTS_OEPINT) - { + if (int_status & GINTSTS_OEPINT) { // OEPINT is read-only, clear using DOEPINTn handle_epout_irq(rhport); } // IN endpoint interrupt handling. - if(int_status & GINTSTS_IEPINT) - { + if (int_status & GINTSTS_IEPINT) { // IEPINT bit read-only, clear using DIEPINTn handle_epin_irq(rhport); } diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_bcm.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_bcm.h similarity index 100% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_bcm.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_bcm.h diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_efm32.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_efm32.h similarity index 100% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_efm32.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_efm32.h diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_esp32.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_esp32.h similarity index 100% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_esp32.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_esp32.h diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_gd32.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_gd32.h similarity index 100% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_gd32.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_gd32.h diff --git a/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md new file mode 100644 index 00000000..8690a075 --- /dev/null +++ b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md @@ -0,0 +1,55 @@ +| | BCM2711 (Pi4) | EFM32GG FullSpeed | ESP32-S2 | STM32F407 Fullspeed | STM32F407 Highspeed | STM32F411 Fullspeed | STM32F412 Fullspeed | STM32F429 Fullspeed | STM32F429 Highspeed | STM32F723 Fullspeed | STM32F723 HighSpeed | STM32F767 Fullspeed | STM32H743 Highspeed | STM32L476 Fullspeed | STM32U5A5 Highspeed | GD32VF103 Fullspeed | XMC4500 | +|:----------------------------|:----------------|:--------------------|:-----------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:-----------| +| guid | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00001200 | 0x00001100 | 0x00003000 | 0x00003100 | 0x00002000 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00001000 | 0x00AEC000 | +| gsnpsid | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54281A | 0x4F54281A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x00000000 | 0x4F54292A | +| - specs version | 2.80a | 3.30a | 4.00a | 2.81a | 2.81a | 2.81a | 3.20a | 2.81a | 2.81a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 0.00W | 2.92a | +| ghwcfg1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| ghwcfg2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x229DCD20 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229FE1D0 | 0x229ED520 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x00000000 | 0x228F5930 | +| - op_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | +| - arch | 2 | 2 | 2 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | +| - point2point | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | +| - hs_phy_type | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 3 | 0 | 2 | 0 | 1 | 0 | 0 | +| - fs_phy_type | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - num_dev_ep | 7 | 6 | 6 | 3 | 5 | 3 | 5 | 3 | 5 | 5 | 8 | 5 | 8 | 5 | 8 | 0 | 6 | +| - num_host_ch | 7 | 13 | 7 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 15 | 11 | 15 | 11 | 15 | 0 | 13 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - mul_cpu_int | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nperiod_tx_q_depth | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 | +| - host_period_tx_q_depth | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 | +| - dev_token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 8 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| ghwcfg3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x020001E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x03EED2E8 | 0x0200D1E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x00000000 | 0x027A01E5 | +| - xfer_size_width | 8 | 8 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 5 | +| - packet_size_width | 6 | 6 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | 6 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - i2c_enable | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | +| - vendor_ctrl_itf | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - total_fifo_size | 4080 | 498 | 200 | 512 | 1012 | 512 | 512 | 512 | 1012 | 512 | 1006 | 512 | 952 | 512 | 952 | 0 | 634 | +| ghwcfg4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0x0FF08030 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x23F00030 | 0x17F08030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0x00000000 | 0xDBF08030 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - power_optimized | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | +| - service_interval_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_en | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - reserved13 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - utmi_phy_data_width | 0 | 2 | 2 | 2 | 0 | 2 | 2 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 0 | 2 | +| - dev_ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - vbus_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - a_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - b_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - num_dev_in_eps | 15 | 13 | 9 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 1 | 11 | 1 | 11 | 1 | 0 | 13 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | +| - dma_dynamic | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | diff --git a/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py new file mode 100644 index 00000000..55bec3d2 --- /dev/null +++ b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py @@ -0,0 +1,169 @@ +import click +import ctypes +import pandas as pd + +# hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 +dwc2_reg_list = ['guid', 'gsnpsid', 'ghwcfg1', 'ghwcfg2', 'ghwcfg3', 'ghwcfg4'] +dwc2_reg_value = { + 'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020], + 'EFM32GG FullSpeed': [0, 0x4F54330A, 0, 0x228F5910, 0x1F204E8, 0x1BF08030], + 'ESP32-S2': [0, 0x4F54400A, 0, 0x224DD930, 0xC804B5, 0xD3F0A030], + 'STM32F407 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F407 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030], + 'STM32F411 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F412 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32F429 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F429 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030], + 'STM32F723 Fullspeed': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32F723 HighSpeed': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x3EED2E8, 0x23F00030], + 'STM32F767 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32H743 Highspeed': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x3B8D2E8, 0xE3F00030], # both HS cores + 'STM32L476 Fullspeed': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32U5A5 Highspeed': [0x00005000, 0x4F54411A, 0x00000000, 0x228FE052, 0x03B882E8, 0xE2103E30], + 'GD32VF103 Fullspeed': [0x1000, 0, 0, 0, 0, 0], + 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x27A01E5, 0xDBF08030] +} + +# Combine dwc2_info with dwc2_reg_list +# dwc2_info = { +# 'BCM2711 (Pi4)': { +# 'guid': 0x2708A000, +# 'gsnpsid': 0x4F54280A, +# 'ghwcfg1': 0, +# 'ghwcfg2': 0x228DDD50, +# 'ghwcfg3': 0xFF000E8, +# 'ghwcfg4': 0x1FF00020 +# }, +dwc2_info = {key: {field: value for field, value in zip(dwc2_reg_list, values)} for key, values in dwc2_reg_value.items()} + + +class GHWCFG2(ctypes.LittleEndianStructure): + _fields_ = [ + ("op_mode", ctypes.c_uint32, 3), + ("arch", ctypes.c_uint32, 2), + ("point2point", ctypes.c_uint32, 1), + ("hs_phy_type", ctypes.c_uint32, 2), + ("fs_phy_type", ctypes.c_uint32, 2), + ("num_dev_ep", ctypes.c_uint32, 4), + ("num_host_ch", ctypes.c_uint32, 4), + ("period_channel_support", ctypes.c_uint32, 1), + ("enable_dynamic_fifo", ctypes.c_uint32, 1), + ("mul_cpu_int", ctypes.c_uint32, 1), + ("reserved21", ctypes.c_uint32, 1), + ("nperiod_tx_q_depth", ctypes.c_uint32, 2), + ("host_period_tx_q_depth", ctypes.c_uint32, 2), + ("dev_token_q_depth", ctypes.c_uint32, 5), + ("otg_enable_ic_usb", ctypes.c_uint32, 1) + ] + + +class GHWCFG3(ctypes.LittleEndianStructure): + _fields_ = [ + ("xfer_size_width", ctypes.c_uint32, 4), + ("packet_size_width", ctypes.c_uint32, 3), + ("otg_enable", ctypes.c_uint32, 1), + ("i2c_enable", ctypes.c_uint32, 1), + ("vendor_ctrl_itf", ctypes.c_uint32, 1), + ("optional_feature_removed", ctypes.c_uint32, 1), + ("synch_reset", ctypes.c_uint32, 1), + ("otg_adp_support", ctypes.c_uint32, 1), + ("otg_enable_hsic", ctypes.c_uint32, 1), + ("battery_charger_support", ctypes.c_uint32, 1), + ("lpm_mode", ctypes.c_uint32, 1), + ("total_fifo_size", ctypes.c_uint32, 16) + ] + + +class GHWCFG4(ctypes.LittleEndianStructure): + _fields_ = [ + ("num_dev_period_in_ep", ctypes.c_uint32, 4), + ("power_optimized", ctypes.c_uint32, 1), + ("ahb_freq_min", ctypes.c_uint32, 1), + ("hibernation", ctypes.c_uint32, 1), + ("reserved7", ctypes.c_uint32, 3), + ("service_interval_mode", ctypes.c_uint32, 1), + ("ipg_isoc_en", ctypes.c_uint32, 1), + ("acg_enable", ctypes.c_uint32, 1), + ("reserved13", ctypes.c_uint32, 1), + ("utmi_phy_data_width", ctypes.c_uint32, 2), + ("dev_ctrl_ep_num", ctypes.c_uint32, 4), + ("iddg_filter_enabled", ctypes.c_uint32, 1), + ("vbus_valid_filter_enabled", ctypes.c_uint32, 1), + ("a_valid_filter_enabled", ctypes.c_uint32, 1), + ("b_valid_filter_enabled", ctypes.c_uint32, 1), + ("dedicated_fifos", ctypes.c_uint32, 1), + ("num_dev_in_eps", ctypes.c_uint32, 4), + ("dma_desc_enable", ctypes.c_uint32, 1), + ("dma_dynamic", ctypes.c_uint32, 1) + ] + + +@click.group() +def cli(): + pass + + +@cli.command() +@click.argument('mcus', nargs=-1) +@click.option('-a', '--all', is_flag=True, help='Print all bit-field values') +def info(mcus, all): + """Print DWC2 register values for given MCU(s)""" + if len(mcus) == 0: + mcus = dwc2_info + + for mcu in mcus: + for entry in dwc2_info: + if mcu.lower() in entry.lower(): + print(f"## {entry}") + for r_name, r_value in dwc2_info[entry].items(): + print(f"{r_name} = 0x{r_value:08X}") + # Print bit-field values + if all and r_name.upper() in globals(): + class_name = globals()[r_name.upper()] + ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little')) + for field_name, field_type, _ in class_name._fields_: + print(f" {field_name} = {getattr(ghwcfg, field_name)}") + + +@cli.command() +def render_md(): + """Render dwc2_info to Markdown table""" + # Create an empty list to hold the dictionaries + dwc2_info_list = [] + + # Iterate over the dwc2_info dictionary and extract fields + for device, reg_values in dwc2_info.items(): + entry_dict = {"Device": device} + for r_name, r_value in reg_values.items(): + entry_dict[r_name] = f"0x{r_value:08X}" + + if r_name == 'gsnpsid': + # Get dwc2 specs version + major = ((r_value >> 8) >> 4) & 0x0F + minor = (r_value >> 4) & 0xFF + patch = chr((r_value & 0x0F) + ord('a') - 0xA) + entry_dict[f' - specs version'] = f"{major:X}.{minor:02X}{patch}" + elif r_name.upper() in globals(): + # Get bit-field values which exist as ctypes structures + class_name = globals()[r_name.upper()] + ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little')) + for field_name, field_type, _ in class_name._fields_: + entry_dict[f' - {field_name}'] = getattr(ghwcfg, field_name) + + dwc2_info_list.append(entry_dict) + + # Create a Pandas DataFrame from the list of dictionaries + df = pd.DataFrame(dwc2_info_list).set_index('Device') + + # Transpose the DataFrame to switch rows and columns + df = df.T + #print(df) + + # Write the Markdown table to a file + with open('dwc2_info.md', 'w') as md_file: + md_file.write(df.to_markdown()) + md_file.write('\n') + + +if __name__ == '__main__': + cli() diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_stm32.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h similarity index 63% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_stm32.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h index cb455bd9..3237a50f 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_stm32.h +++ b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h @@ -24,11 +24,11 @@ * This file is part of the TinyUSB stack. */ -#ifndef _DWC2_STM32_H_ -#define _DWC2_STM32_H_ +#ifndef DWC2_STM32_H_ +#define DWC2_STM32_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif // EP_MAX : Max number of bi-directional endpoints including EP0 @@ -84,10 +84,16 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" - #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 - + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY + #ifdef USB_OTG_FS + #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + #else + #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 + #endif #else #error "Unsupported MCUs" #endif @@ -101,15 +107,14 @@ // On STM32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS -static const dwc2_controller_t _dwc2_controller[] = -{ -#ifdef USB_OTG_FS_PERIPH_BASE - { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, -#endif - -#ifdef USB_OTG_HS_PERIPH_BASE - { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS }, -#endif +static const dwc2_controller_t _dwc2_controller[] = { + #ifdef USB_OTG_FS_PERIPH_BASE + { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + #endif + + #ifdef USB_OTG_HS_PERIPH_BASE + { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS }, + #endif }; //--------------------------------------------------------------------+ @@ -119,42 +124,59 @@ static const dwc2_controller_t _dwc2_controller[] = // SystemCoreClock is already included by family header // extern uint32_t SystemCoreClock; -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_enable(uint8_t rhport) -{ - NVIC_EnableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum); +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { + NVIC_EnableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum); } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_disable (uint8_t rhport) -{ - NVIC_DisableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum); +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum); } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_remote_wakeup_delay(void) -{ +TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while ( count-- ) __NOP(); + while (count--) __NOP(); } // MCU specific PHY init, called BEFORE core reset -static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ - if ( hs_phy_type == HS_PHY_TYPE_NONE ) - { +// - dwc2 3.30a (H5) use USB_HS_PHYC +// - dwc2 4.11a (U5) use femtoPHY +static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { + if (hs_phy_type == HS_PHY_TYPE_NONE) { // Enable on-chip FS PHY dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN; - }else - { - // Disable FS PHY + + // https://community.st.com/t5/stm32cubemx-mcus/why-stm32h743-usb-fs-doesn-t-work-if-freertos-tickless-idle/m-p/349480#M18867 + // H7 running on full-speed phy need to disable ULPI clock in sleep mode. + // Otherwise, USB won't work when mcu executing WFI/WFE instruction i.e tick-less RTOS. + // Note: there may be other family that is affected by this, but only H7 and F7 is tested so far + #if defined(USB_OTG_FS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB2OTGFSULPILPEN) + if ( USB_OTG_FS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB2OTGFSULPILPEN; + } + #endif + + #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB1OTGHSULPILPEN) + if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB1OTGHSULPILPEN; + } + #endif + + #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_OTGHSULPILPEN) + if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_OTGHSULPILPEN; + } + #endif + + } else { +#if CFG_TUSB_MCU != OPT_MCU_STM32U5 + // Disable FS PHY, TODO on U5A5 (dwc2 4.11a) 16th bit is 'Host CDP behavior enable' dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; +#endif // Enable on-chip HS PHY - if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) - { -#ifdef USB_HS_PHYC + if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) { + #ifdef USB_HS_PHYC // Enable UTMI HS PHY dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN; @@ -186,40 +208,47 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) // Enable PLL internal PHY USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; -#endif + #else + + #endif } } } // MCU specific PHY update, it is called AFTER init() and core reset -static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ +static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { // used to set turnaround time for fullspeed, nothing to do in highspeed mode - if ( hs_phy_type == HS_PHY_TYPE_NONE ) - { + if (hs_phy_type == HS_PHY_TYPE_NONE) { // Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual uint32_t turnaround; - if ( SystemCoreClock >= 32000000u ) + if (SystemCoreClock >= 32000000u) { turnaround = 0x6u; - else if ( SystemCoreClock >= 27500000u ) + } else if (SystemCoreClock >= 27500000u) { turnaround = 0x7u; - else if ( SystemCoreClock >= 24000000u ) + } else if (SystemCoreClock >= 24000000u) { turnaround = 0x8u; - else if ( SystemCoreClock >= 21800000u ) + } else if (SystemCoreClock >= 21800000u) { turnaround = 0x9u; - else if ( SystemCoreClock >= 20000000u ) + } + else if (SystemCoreClock >= 20000000u) { turnaround = 0xAu; - else if ( SystemCoreClock >= 18500000u ) + } + else if (SystemCoreClock >= 18500000u) { turnaround = 0xBu; - else if ( SystemCoreClock >= 17200000u ) + } + else if (SystemCoreClock >= 17200000u) { turnaround = 0xCu; - else if ( SystemCoreClock >= 16000000u ) + } + else if (SystemCoreClock >= 16000000u) { turnaround = 0xDu; - else if ( SystemCoreClock >= 15000000u ) + } + else if (SystemCoreClock >= 15000000u) { turnaround = 0xEu; - else + } + else { turnaround = 0xFu; + } dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos); } @@ -229,4 +258,4 @@ static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } #endif -#endif /* _DWC2_STM32_H_ */ +#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_type.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h similarity index 71% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_type.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h index 3fc97933..c1577123 100644 --- a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_type.h +++ b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h @@ -32,7 +32,7 @@ typedef struct uint32_t ep_fifo_size; }dwc2_controller_t; -/* DWC OTG HW Release versions */ +// DWC OTG HW Release versions #define DWC2_CORE_REV_2_71a 0x4f54271a #define DWC2_CORE_REV_2_72a 0x4f54272a #define DWC2_CORE_REV_2_80a 0x4f54280a @@ -43,12 +43,13 @@ typedef struct #define DWC2_CORE_REV_3_00a 0x4f54300a #define DWC2_CORE_REV_3_10a 0x4f54310a #define DWC2_CORE_REV_4_00a 0x4f54400a +#define DWC2_CORE_REV_4_11a 0x4f54411a #define DWC2_CORE_REV_4_20a 0x4f54420a #define DWC2_FS_IOT_REV_1_00a 0x5531100a #define DWC2_HS_IOT_REV_1_00a 0x5532100a #define DWC2_CORE_REV_MASK 0x0000ffff -/* DWC OTG HW Core ID */ +// DWC OTG HW Core ID #define DWC2_OTG_ID 0x4f540000 #define DWC2_FS_IOT_ID 0x55310000 #define DWC2_HS_IOT_ID 0x55320000 @@ -57,13 +58,13 @@ typedef struct // HS PHY typedef struct { - volatile uint32_t HS_PHYC_PLL; // This register is used to control the PLL of the HS PHY. 000h */ - volatile uint32_t Reserved04; // Reserved 004h */ - volatile uint32_t Reserved08; // Reserved 008h */ - volatile uint32_t HS_PHYC_TUNE; // This register is used to control the tuning interface of the High Speed PHY. 00Ch */ - volatile uint32_t Reserved10; // Reserved 010h */ - volatile uint32_t Reserved14; // Reserved 014h */ - volatile uint32_t HS_PHYC_LDO; // This register is used to control the regulator (LDO). 018h */ + volatile uint32_t HS_PHYC_PLL; // 000h This register is used to control the PLL of the HS PHY. + volatile uint32_t Reserved04; // 004h Reserved + volatile uint32_t Reserved08; // 008h Reserved + volatile uint32_t HS_PHYC_TUNE; // 00Ch This register is used to control the tuning interface of the High Speed PHY. + volatile uint32_t Reserved10; // 010h Reserved + volatile uint32_t Reserved14; // 014h Reserved + volatile uint32_t HS_PHYC_LDO; // 018h This register is used to control the regulator (LDO). } HS_PHYC_GlobalTypeDef; #endif @@ -298,103 +299,103 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); /******************** Bit definition for GOTGCTL register ********************/ #define GOTGCTL_SRQSCS_Pos (0U) -#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 */ -#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success */ +#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 +#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success #define GOTGCTL_SRQ_Pos (1U) -#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 */ -#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request */ +#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 +#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request #define GOTGCTL_VBVALOEN_Pos (2U) -#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 */ -#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable */ +#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 +#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable #define GOTGCTL_VBVALOVAL_Pos (3U) -#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 */ -#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value */ +#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 +#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value #define GOTGCTL_AVALOEN_Pos (4U) -#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 */ -#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable */ +#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 +#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable #define GOTGCTL_AVALOVAL_Pos (5U) -#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 */ -#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value */ +#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 +#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value #define GOTGCTL_BVALOEN_Pos (6U) -#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 */ -#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable */ +#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 +#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable #define GOTGCTL_BVALOVAL_Pos (7U) -#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 */ -#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value */ +#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 +#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value #define GOTGCTL_HNGSCS_Pos (8U) -#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 */ -#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable */ +#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 +#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable #define GOTGCTL_HNPRQ_Pos (9U) -#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 */ -#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request */ +#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 +#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request #define GOTGCTL_HSHNPEN_Pos (10U) -#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 */ -#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable */ +#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 +#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable #define GOTGCTL_DHNPEN_Pos (11U) -#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 */ -#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled */ +#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 +#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled #define GOTGCTL_EHEN_Pos (12U) -#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 */ -#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable */ +#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 +#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable #define GOTGCTL_CIDSTS_Pos (16U) -#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 */ -#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status */ +#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 +#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status #define GOTGCTL_DBCT_Pos (17U) -#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 */ -#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time */ +#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 +#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time #define GOTGCTL_ASVLD_Pos (18U) -#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 */ -#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid */ +#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 +#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid #define GOTGCTL_BSESVLD_Pos (19U) -#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 */ -#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid */ +#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 +#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid #define GOTGCTL_OTGVER_Pos (20U) -#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 */ -#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version */ +#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 +#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version /******************** Bit definition for HCFG register ********************/ #define HCFG_FSLSPCS_Pos (0U) -#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 */ -#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select */ -#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 */ -#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 */ +#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 +#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select +#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 +#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 #define HCFG_FSLSS_Pos (2U) -#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 */ -#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support */ +#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 +#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support /******************** Bit definition for PCGCR register ********************/ #define PCGCR_STPPCLK_Pos (0U) -#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 */ -#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock */ +#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 +#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock #define PCGCR_GATEHCLK_Pos (1U) -#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 */ -#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK */ +#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 +#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK #define PCGCR_PHYSUSP_Pos (4U) -#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 */ -#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended */ +#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 +#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended /******************** Bit definition for GOTGINT register ********************/ #define GOTGINT_SEDET_Pos (2U) -#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 */ -#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected */ +#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 +#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected #define GOTGINT_SRSSCHG_Pos (8U) -#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 */ -#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change */ +#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 +#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change #define GOTGINT_HNSSCHG_Pos (9U) -#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 */ -#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change */ +#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 +#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change #define GOTGINT_HNGDET_Pos (17U) -#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 */ -#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected */ +#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 +#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected #define GOTGINT_ADTOCHG_Pos (18U) -#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 */ -#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change */ +#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 +#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change #define GOTGINT_DBCDNE_Pos (19U) -#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 */ -#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done */ +#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 +#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done #define GOTGINT_IDCHNG_Pos (20U) -#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 */ -#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value */ +#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 +#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value /******************** Bit definition for DCFG register ********************/ #define DCFG_DSPD_Pos (0U) @@ -405,92 +406,92 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DCFG_DSPD_FS 3 // Fullspeed on FS PHY #define DCFG_NZLSOHSK_Pos (2U) -#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 */ -#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake */ +#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 +#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake #define DCFG_DAD_Pos (4U) -#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 */ -#define DCFG_DAD DCFG_DAD_Msk // Device address */ -#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 */ -#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 */ -#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 */ -#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 */ -#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 */ -#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 */ -#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 */ +#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 +#define DCFG_DAD DCFG_DAD_Msk // Device address +#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 +#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 +#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 +#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 +#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 +#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 +#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 #define DCFG_PFIVL_Pos (11U) -#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 */ -#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval */ -#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 */ -#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 */ +#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 +#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval +#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 +#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 #define DCFG_XCVRDLY_Pos (14U) -#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) /*!< 0x00004000 */ +#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) // 0x00004000 #define DCFG_XCVRDLY DCFG_XCVRDLY_Msk // Enables delay between xcvr_sel and txvalid during device chirp #define DCFG_PERSCHIVL_Pos (24U) -#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 */ -#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval */ -#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 */ -#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 */ +#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 +#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval +#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 +#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 /******************** Bit definition for DCTL register ********************/ #define DCTL_RWUSIG_Pos (0U) -#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 */ -#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling */ +#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 +#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling #define DCTL_SDIS_Pos (1U) -#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 */ -#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect */ +#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 +#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect #define DCTL_GINSTS_Pos (2U) -#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 */ -#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status */ +#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 +#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status #define DCTL_GONSTS_Pos (3U) -#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 */ -#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status */ +#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 +#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status #define DCTL_TCTL_Pos (4U) -#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 */ -#define DCTL_TCTL DCTL_TCTL_Msk // Test control */ -#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 */ -#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 */ -#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 */ +#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 +#define DCTL_TCTL DCTL_TCTL_Msk // Test control +#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 +#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 +#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 #define DCTL_SGINAK_Pos (7U) -#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 */ -#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK */ +#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 +#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK #define DCTL_CGINAK_Pos (8U) -#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 */ -#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK */ +#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 +#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK #define DCTL_SGONAK_Pos (9U) -#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 */ -#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK */ +#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 +#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK #define DCTL_CGONAK_Pos (10U) -#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 */ -#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK */ +#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 +#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK #define DCTL_POPRGDNE_Pos (11U) -#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 */ -#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done */ +#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 +#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done /******************** Bit definition for HFIR register ********************/ #define HFIR_FRIVL_Pos (0U) -#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF */ -#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval */ +#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF +#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval /******************** Bit definition for HFNUM register ********************/ #define HFNUM_FRNUM_Pos (0U) -#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF */ -#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number */ +#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF +#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number #define HFNUM_FTREM_Pos (16U) -#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 */ -#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining */ +#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 +#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining /******************** Bit definition for DSTS register ********************/ #define DSTS_SUSPSTS_Pos (0U) -#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 */ -#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status */ +#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 +#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status #define DSTS_ENUMSPD_Pos (1U) -#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 */ -#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed */ +#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 +#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed #define DSTS_ENUMSPD_HS 0 // Highspeed #define DSTS_ENUMSPD_FS_HSPHY 1 // Fullspeed on HS PHY #define DSTS_ENUMSPD_LS 2 // Lowspeed @@ -498,427 +499,427 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DSTS_EERR_Pos (3U) -#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 */ -#define DSTS_EERR DSTS_EERR_Msk // Erratic error */ +#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 +#define DSTS_EERR DSTS_EERR_Msk // Erratic error #define DSTS_FNSOF_Pos (8U) -#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 */ -#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF */ +#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 +#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF /******************** Bit definition for GAHBCFG register ********************/ #define GAHBCFG_GINT_Pos (0U) -#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 */ -#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask */ +#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 +#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask #define GAHBCFG_HBSTLEN_Pos (1U) -#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E */ -#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type */ -#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single */ -#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR */ -#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 */ -#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 */ -#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 */ +#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E +#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type +#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single +#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR +#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 +#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 +#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 #define GAHBCFG_DMAEN_Pos (5U) -#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 */ -#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable */ +#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 +#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable #define GAHBCFG_TXFELVL_Pos (7U) -#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 */ -#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level */ +#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 +#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level #define GAHBCFG_PTXFELVL_Pos (8U) -#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 */ -#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level */ +#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 +#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level #define GSNPSID_ID_MASK TU_GENMASK(31, 16) /******************** Bit definition for GUSBCFG register ********************/ #define GUSBCFG_TOCAL_Pos (0U) -#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 */ -#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration */ +#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 +#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration #define GUSBCFG_PHYIF16_Pos (3U) -#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 */ -#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) */ +#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 +#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) #define GUSBCFG_ULPI_UTMI_SEL_Pos (4U) -#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 */ -#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) */ +#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 +#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) #define GUSBCFG_PHYSEL_Pos (6U) -#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 */ -#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ +#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 +#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select #define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface. #define GUSBCFG_SRPCAP_Pos (8U) -#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 */ -#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable */ +#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 +#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable #define GUSBCFG_HNPCAP_Pos (9U) -#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 */ -#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable */ +#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 +#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable #define GUSBCFG_TRDT_Pos (10U) -#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 */ -#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time */ +#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 +#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time #define GUSBCFG_PHYLPCS_Pos (15U) -#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 */ -#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select */ +#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 +#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select #define GUSBCFG_ULPIFSLS_Pos (17U) -#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 */ -#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select */ +#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 +#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select #define GUSBCFG_ULPIAR_Pos (18U) -#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 */ -#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume */ +#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 +#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume #define GUSBCFG_ULPICSM_Pos (19U) -#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 */ -#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM */ +#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 +#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM #define GUSBCFG_ULPIEVBUSD_Pos (20U) -#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 */ -#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive */ +#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 +#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive #define GUSBCFG_ULPIEVBUSI_Pos (21U) -#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 */ -#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator */ +#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 +#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator #define GUSBCFG_TSDPS_Pos (22U) -#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 */ -#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection */ +#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 +#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection #define GUSBCFG_PCCI_Pos (23U) -#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 */ -#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement */ +#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 +#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement #define GUSBCFG_PTCI_Pos (24U) -#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 */ -#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through */ +#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 +#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through #define GUSBCFG_ULPIIPD_Pos (25U) -#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 */ -#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable */ +#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 +#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable #define GUSBCFG_FHMOD_Pos (29U) -#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 */ -#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode */ +#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 +#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode #define GUSBCFG_FDMOD_Pos (30U) -#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 */ -#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode */ +#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 +#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode #define GUSBCFG_CTXPKT_Pos (31U) -#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 */ -#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet */ +#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 +#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet /******************** Bit definition for GRSTCTL register ********************/ #define GRSTCTL_CSRST_Pos (0U) -#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 */ -#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset */ +#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 +#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset #define GRSTCTL_HSRST_Pos (1U) -#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 */ -#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset */ +#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 +#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset #define GRSTCTL_FCRST_Pos (2U) -#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 */ -#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset */ +#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 +#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset #define GRSTCTL_RXFFLSH_Pos (4U) -#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 */ -#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush */ +#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 +#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush #define GRSTCTL_TXFFLSH_Pos (5U) -#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 */ -#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush */ +#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 +#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush #define GRSTCTL_TXFNUM_Pos (6U) -#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 */ -#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number */ -#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 */ -#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 */ -#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 */ -#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 */ -#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 */ +#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 +#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number +#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 +#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 +#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 +#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 +#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 #define GRSTCTL_CSFTRST_DONE_Pos (29) #define GRSTCTL_CSFTRST_DONE (1u << GRSTCTL_CSFTRST_DONE_Pos) // Reset Done, only available from v4.20a #define GRSTCTL_DMAREQ_Pos (30U) -#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 */ -#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal */ +#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 +#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal #define GRSTCTL_AHBIDL_Pos (31U) -#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 */ -#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle */ +#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 +#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle /******************** Bit definition for DIEPMSK register ********************/ #define DIEPMSK_XFRCM_Pos (0U) -#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 */ -#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 +#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask #define DIEPMSK_EPDM_Pos (1U) -#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 */ -#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 +#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask #define DIEPMSK_TOM_Pos (3U) -#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 */ -#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 +#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) #define DIEPMSK_ITTXFEMSK_Pos (4U) -#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 */ -#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 +#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DIEPMSK_INEPNMM_Pos (5U) -#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 */ -#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 +#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask #define DIEPMSK_INEPNEM_Pos (6U) -#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 */ -#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 +#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask #define DIEPMSK_TXFURM_Pos (8U) -#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 */ -#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask */ +#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 +#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask #define DIEPMSK_BIM_Pos (9U) -#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 */ -#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask */ +#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 +#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask /******************** Bit definition for HPTXSTS register ********************/ #define HPTXSTS_PTXFSAVL_Pos (0U) -#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF */ -#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available */ +#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF +#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available #define HPTXSTS_PTXQSAV_Pos (16U) -#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 */ -#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available */ -#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 */ -#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 */ -#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 */ -#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 */ -#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 */ -#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 */ -#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 */ -#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 */ +#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 +#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available +#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 +#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 +#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 +#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 +#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 +#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 +#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 +#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 #define HPTXSTS_PTXQTOP_Pos (24U) -#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 */ -#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue */ -#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 */ -#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 */ -#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 */ -#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 */ -#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 */ -#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 */ -#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 */ -#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 */ +#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 +#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue +#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 +#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 +#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 +#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 +#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 +#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 +#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 +#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 /******************** Bit definition for HAINT register ********************/ #define HAINT_HAINT_Pos (0U) -#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF */ -#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts */ +#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF +#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts /******************** Bit definition for DOEPMSK register ********************/ #define DOEPMSK_XFRCM_Pos (0U) -#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 */ -#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 +#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask #define DOEPMSK_EPDM_Pos (1U) -#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 */ -#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 +#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask #define DOEPMSK_AHBERRM_Pos (2U) -#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 */ -#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask */ +#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 +#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask #define DOEPMSK_STUPM_Pos (3U) -#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 */ -#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask */ +#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 +#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask #define DOEPMSK_OTEPDM_Pos (4U) -#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 */ -#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask */ +#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 +#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask #define DOEPMSK_OTEPSPRM_Pos (5U) -#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 */ -#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask */ +#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 +#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask #define DOEPMSK_B2BSTUP_Pos (6U) -#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 */ -#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask */ +#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 +#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask #define DOEPMSK_OPEM_Pos (8U) -#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 */ -#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask */ +#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 +#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask #define DOEPMSK_BOIM_Pos (9U) -#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 */ -#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask */ +#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 +#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask #define DOEPMSK_BERRM_Pos (12U) -#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 */ -#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask */ +#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 +#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask #define DOEPMSK_NAKM_Pos (13U) -#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 */ -#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask */ +#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 +#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask #define DOEPMSK_NYETM_Pos (14U) -#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 */ -#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask */ +#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 +#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask /******************** Bit definition for GINTSTS register ********************/ #define GINTSTS_CMOD_Pos (0U) -#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 */ -#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation */ +#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 +#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation #define GINTSTS_MMIS_Pos (1U) -#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 */ -#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt */ +#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 +#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt #define GINTSTS_OTGINT_Pos (2U) -#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 */ -#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt */ +#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 +#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt #define GINTSTS_SOF_Pos (3U) -#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 */ -#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame */ +#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 +#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame #define GINTSTS_RXFLVL_Pos (4U) -#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 */ -#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty */ +#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 +#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty #define GINTSTS_NPTXFE_Pos (5U) -#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 */ -#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty */ +#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 +#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty #define GINTSTS_GINAKEFF_Pos (6U) -#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 */ -#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective */ +#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 +#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective #define GINTSTS_BOUTNAKEFF_Pos (7U) -#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 */ -#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective */ +#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 +#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective #define GINTSTS_ESUSP_Pos (10U) -#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 */ -#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend */ +#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 +#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend #define GINTSTS_USBSUSP_Pos (11U) -#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 */ -#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend */ +#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 +#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend #define GINTSTS_USBRST_Pos (12U) -#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 */ -#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset */ +#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 +#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset #define GINTSTS_ENUMDNE_Pos (13U) -#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 */ -#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done */ +#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 +#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done #define GINTSTS_ISOODRP_Pos (14U) -#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 */ -#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt */ +#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 +#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt #define GINTSTS_EOPF_Pos (15U) -#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 */ -#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt */ +#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 +#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt #define GINTSTS_IEPINT_Pos (18U) -#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 */ -#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt */ +#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 +#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt #define GINTSTS_OEPINT_Pos (19U) -#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 */ -#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt */ +#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 +#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt #define GINTSTS_IISOIXFR_Pos (20U) -#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 */ -#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer */ +#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 +#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer #define GINTSTS_PXFR_INCOMPISOOUT_Pos (21U) -#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 */ -#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer */ +#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 +#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer #define GINTSTS_DATAFSUSP_Pos (22U) -#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 */ -#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended */ +#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 +#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended #define GINTSTS_RSTDET_Pos (23U) -#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 */ -#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt */ +#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 +#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt #define GINTSTS_HPRTINT_Pos (24U) -#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 */ -#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt */ +#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 +#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt #define GINTSTS_HCINT_Pos (25U) -#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 */ -#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt */ +#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 +#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt #define GINTSTS_PTXFE_Pos (26U) -#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 */ -#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty */ +#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 +#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty #define GINTSTS_LPMINT_Pos (27U) -#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 */ -#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt */ +#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 +#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt #define GINTSTS_CIDSCHG_Pos (28U) -#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 */ -#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change */ +#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 +#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change #define GINTSTS_DISCINT_Pos (29U) -#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 */ -#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt */ +#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 +#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt #define GINTSTS_SRQINT_Pos (30U) -#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 */ -#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt */ +#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 +#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt #define GINTSTS_WKUINT_Pos (31U) -#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 */ -#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt */ +#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 +#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt /******************** Bit definition for GINTMSK register ********************/ #define GINTMSK_MMISM_Pos (1U) -#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 */ -#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask */ +#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 +#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask #define GINTMSK_OTGINT_Pos (2U) -#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 */ -#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask */ +#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 +#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask #define GINTMSK_SOFM_Pos (3U) -#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 */ -#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask */ +#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 +#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask #define GINTMSK_RXFLVLM_Pos (4U) -#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 */ -#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask */ +#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 +#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask #define GINTMSK_NPTXFEM_Pos (5U) -#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 */ -#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask */ +#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 +#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask #define GINTMSK_GINAKEFFM_Pos (6U) -#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 */ -#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask */ +#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 +#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask #define GINTMSK_GONAKEFFM_Pos (7U) -#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 */ -#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask */ +#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 +#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask #define GINTMSK_ESUSPM_Pos (10U) -#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 */ -#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask */ +#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 +#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask #define GINTMSK_USBSUSPM_Pos (11U) -#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 */ -#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask */ +#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 +#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask #define GINTMSK_USBRST_Pos (12U) -#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 */ -#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask */ +#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 +#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask #define GINTMSK_ENUMDNEM_Pos (13U) -#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 */ -#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask */ +#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 +#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask #define GINTMSK_ISOODRPM_Pos (14U) -#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 */ -#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask */ +#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 +#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask #define GINTMSK_EOPFM_Pos (15U) -#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 */ -#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask */ +#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 +#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask #define GINTMSK_EPMISM_Pos (17U) -#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 */ -#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask */ +#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 +#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask #define GINTMSK_IEPINT_Pos (18U) -#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 */ -#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask */ +#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 +#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask #define GINTMSK_OEPINT_Pos (19U) -#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 */ -#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask */ +#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 +#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask #define GINTMSK_IISOIXFRM_Pos (20U) -#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 */ -#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask */ +#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 +#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask #define GINTMSK_PXFRM_IISOOXFRM_Pos (21U) -#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 */ -#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask */ +#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 +#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask #define GINTMSK_FSUSPM_Pos (22U) -#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 */ -#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask */ +#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 +#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask #define GINTMSK_RSTDEM_Pos (23U) -#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 */ -#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask */ +#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 +#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask #define GINTMSK_PRTIM_Pos (24U) -#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 */ -#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask */ +#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 +#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask #define GINTMSK_HCIM_Pos (25U) -#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 */ -#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask */ +#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 +#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask #define GINTMSK_PTXFEM_Pos (26U) -#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 */ -#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask */ +#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 +#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask #define GINTMSK_LPMINTM_Pos (27U) -#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 */ -#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask */ +#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 +#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask #define GINTMSK_CIDSCHGM_Pos (28U) -#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 */ -#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask */ +#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 +#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask #define GINTMSK_DISCINT_Pos (29U) -#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 */ -#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask */ +#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 +#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask #define GINTMSK_SRQIM_Pos (30U) -#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 */ -#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask */ +#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 +#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask #define GINTMSK_WUIM_Pos (31U) -#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 */ -#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask */ +#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 +#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask /******************** Bit definition for DAINT register ********************/ #define DAINT_IEPINT_Pos (0U) -#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF */ -#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits */ +#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF +#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits #define DAINT_OEPINT_Pos (16U) -#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 */ -#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits */ +#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 +#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits /******************** Bit definition for HAINTMSK register ********************/ #define HAINTMSK_HAINTM_Pos (0U) -#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF */ -#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask */ +#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF +#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask /******************** Bit definition for GRXSTSP register ********************/ #define GRXSTSP_EPNUM_Pos (0U) -#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F */ -#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits */ +#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F +#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits #define GRXSTSP_BCNT_Pos (4U) -#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 */ -#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 +#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits #define GRXSTSP_DPID_Pos (15U) -#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 */ -#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 +#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits #define GRXSTSP_PKTSTS_Pos (17U) -#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 */ -#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 +#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits #define GRXSTS_PKTSTS_GLOBALOUTNAK 1 #define GRXSTS_PKTSTS_OUTRX 2 @@ -933,773 +934,803 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); /******************** Bit definition for DAINTMSK register ********************/ #define DAINTMSK_IEPM_Pos (0U) -#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF */ -#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits */ +#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF +#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits #define DAINTMSK_OEPM_Pos (16U) -#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 */ -#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits */ +#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 +#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits #if 0 /******************** Bit definition for OTG register ********************/ #define CHNUM_Pos (0U) -#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F */ -#define CHNUM CHNUM_Msk // Channel number */ -#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 */ -#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 */ -#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 */ -#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 */ +#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F +#define CHNUM CHNUM_Msk // Channel number +#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 +#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 +#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 +#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 #define BCNT_Pos (4U) -#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 */ -#define BCNT BCNT_Msk // Byte count */ +#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 +#define BCNT BCNT_Msk // Byte count #define DPID_Pos (15U) -#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 */ -#define DPID DPID_Msk // Data PID */ -#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 */ -#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 */ +#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 +#define DPID DPID_Msk // Data PID +#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 +#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 #define PKTSTS_Pos (17U) -#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 */ -#define PKTSTS PKTSTS_Msk // Packet status */ -#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 */ -#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 */ -#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 */ -#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 */ +#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 +#define PKTSTS PKTSTS_Msk // Packet status +#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 +#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 +#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 +#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 #define EPNUM_Pos (0U) -#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F */ -#define EPNUM EPNUM_Msk // Endpoint number */ -#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 */ -#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 */ -#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 */ -#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 */ +#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F +#define EPNUM EPNUM_Msk // Endpoint number +#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 +#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 +#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 +#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 #define FRMNUM_Pos (21U) -#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 */ -#define FRMNUM FRMNUM_Msk // Frame number */ -#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 */ -#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 */ -#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 */ -#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 */ +#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 +#define FRMNUM FRMNUM_Msk // Frame number +#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 +#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 +#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 +#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 #endif /******************** Bit definition for GRXFSIZ register ********************/ #define GRXFSIZ_RXFD_Pos (0U) -#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF */ -#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth */ +#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF +#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth /******************** Bit definition for DVBUSDIS register ********************/ #define DVBUSDIS_VBUSDT_Pos (0U) -#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF */ -#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time */ +#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF +#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time /******************** Bit definition for OTG register ********************/ #define GNPTXFSIZ_NPTXFSA_Pos (0U) -#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF */ -#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address */ +#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF +#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address #define GNPTXFSIZ_NPTXFD_Pos (16U) -#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 */ -#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth */ +#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 +#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth #define DIEPTXF0_TX0FSA_Pos (0U) -#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF */ -#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address */ +#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF +#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address #define DIEPTXF0_TX0FD_Pos (16U) -#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 */ -#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth */ +#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 +#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth /******************** Bit definition for DVBUSPULSE register ********************/ #define DVBUSPULSE_DVBUSP_Pos (0U) -#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF */ -#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time */ +#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF +#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time /******************** Bit definition for GNPTXSTS register ********************/ #define GNPTXSTS_NPTXFSAV_Pos (0U) -#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF */ -#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available */ +#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF +#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available #define GNPTXSTS_NPTQXSAV_Pos (16U) -#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 */ -#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available */ -#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 */ -#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 */ -#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 */ -#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 */ -#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 */ -#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 */ -#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 */ -#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 */ +#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 +#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available +#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 +#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 +#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 +#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 +#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 +#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 +#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 +#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 #define GNPTXSTS_NPTXQTOP_Pos (24U) -#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 */ -#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue */ -#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 */ -#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 */ -#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 */ -#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 */ -#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 */ -#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 */ -#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 */ +#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 +#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue +#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 +#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 +#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 +#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 +#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 +#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 +#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 /******************** Bit definition for DTHRCTL register ********************/ #define DTHRCTL_NONISOTHREN_Pos (0U) -#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 */ -#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable */ +#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 +#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable #define DTHRCTL_ISOTHREN_Pos (1U) -#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 */ -#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable */ +#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 +#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable #define DTHRCTL_TXTHRLEN_Pos (2U) -#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC */ -#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length */ -#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 */ -#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 */ -#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 */ -#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 */ -#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 */ -#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 */ -#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 */ -#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 */ -#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 */ +#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC +#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length +#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 +#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 +#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 +#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 +#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 +#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 +#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 +#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 +#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 #define DTHRCTL_RXTHREN_Pos (16U) -#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 */ -#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable */ +#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 +#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable #define DTHRCTL_RXTHRLEN_Pos (17U) -#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 */ -#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length */ -#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 */ -#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 */ -#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 */ -#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 */ -#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 */ -#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 */ -#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 */ -#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 */ -#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 */ +#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 +#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length +#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 +#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 +#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 +#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 +#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 +#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 +#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 +#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 +#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 #define DTHRCTL_ARPEN_Pos (27U) -#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 */ -#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable */ +#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 +#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable /******************** Bit definition for DIEPEMPMSK register ********************/ #define DIEPEMPMSK_INEPTXFEM_Pos (0U) -#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF */ -#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits */ +#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF +#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits /******************** Bit definition for DEACHINT register ********************/ #define DEACHINT_IEP1INT_Pos (1U) -#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 */ -#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit */ +#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 +#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit #define DEACHINT_OEP1INT_Pos (17U) -#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 */ -#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit */ +#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 +#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit /******************** Bit definition for GCCFG register ********************/ #define STM32_GCCFG_DCDET_Pos (0U) -#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 */ -#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status */ +#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 +#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status + #define STM32_GCCFG_PDET_Pos (1U) -#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 */ -#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status */ +#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 +#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status + #define STM32_GCCFG_SDET_Pos (2U) -#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 */ -#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status */ +#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 +#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status + #define STM32_GCCFG_PS2DET_Pos (3U) -#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 */ -#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status */ +#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 +#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status + #define STM32_GCCFG_PWRDWN_Pos (16U) -#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 */ -#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down */ +#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 +#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down + #define STM32_GCCFG_BCDEN_Pos (17U) -#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 */ -#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable */ +#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 +#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable + #define STM32_GCCFG_DCDEN_Pos (18U) -#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 */ +#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 #define STM32_GCCFG_DCDEN STM32_GCCFG_DCDEN_Msk // Data contact detection (DCD) mode enable*/ + #define STM32_GCCFG_PDEN_Pos (19U) -#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 */ +#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 #define STM32_GCCFG_PDEN STM32_GCCFG_PDEN_Msk // Primary detection (PD) mode enable*/ + #define STM32_GCCFG_SDEN_Pos (20U) -#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 */ -#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable */ +#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 +#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable + #define STM32_GCCFG_VBDEN_Pos (21U) -#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 */ -#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable */ +#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 +#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable + #define STM32_GCCFG_OTGIDEN_Pos (22U) -#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 */ -#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable */ +#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 +#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable + #define STM32_GCCFG_PHYHSEN_Pos (23U) -#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 */ -#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable */ +#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 +#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable + +// TODO stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above +//#define STM32_GCCFG_SDEN_Pos (22U) +//#define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000 +//#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable + +// TODO stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above +#define STM32_GCCFG_VBVALOVAL_Pos (23U) +#define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000 +#define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input + +#define STM32_GCCFG_VBVALEXTOEN_Pos (24U) +#define STM32_GCCFG_VBVALEXTOEN_Msk (0x1U << STM32_GCCFG_VBVALEXTOEN_Pos) // 0x01000000 +#define STM32_GCCFG_VBVALEXTOEN STM32_GCCFG_VBVALEXTOEN_Msk // Enables of VBUSVLDEXT0 femtoPHY input override + +#define STM32_GCCFG_PULLDOWNEN_Pos (25U) +#define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000 +#define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled + /******************** Bit definition for DEACHINTMSK register ********************/ #define DEACHINTMSK_IEP1INTM_Pos (1U) -#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 */ -#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit */ +#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 +#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit #define DEACHINTMSK_OEP1INTM_Pos (17U) -#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 */ -#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit */ +#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 +#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit /******************** Bit definition for CID register ********************/ #define CID_PRODUCT_ID_Pos (0U) -#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF */ -#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field */ +#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF +#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field /******************** Bit definition for GLPMCFG register ********************/ #define GLPMCFG_LPMEN_Pos (0U) -#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 */ -#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable */ +#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 +#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable #define GLPMCFG_LPMACK_Pos (1U) -#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 */ -#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable */ +#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 +#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable #define GLPMCFG_BESL_Pos (2U) -#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C */ -#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token */ +#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C +#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token #define GLPMCFG_REMWAKE_Pos (6U) -#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 */ -#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token */ +#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 +#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token #define GLPMCFG_L1SSEN_Pos (7U) -#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 */ -#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable */ +#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 +#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable #define GLPMCFG_BESLTHRS_Pos (8U) -#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 */ -#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold */ +#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 +#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold #define GLPMCFG_L1DSEN_Pos (12U) -#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 */ -#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable */ +#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 +#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable #define GLPMCFG_LPMRSP_Pos (13U) -#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 */ -#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response */ +#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 +#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response #define GLPMCFG_SLPSTS_Pos (15U) -#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 */ -#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status */ +#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 +#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status #define GLPMCFG_L1RSMOK_Pos (16U) -#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 */ -#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK */ +#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 +#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK #define GLPMCFG_LPMCHIDX_Pos (17U) -#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 */ -#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index */ +#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 +#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index #define GLPMCFG_LPMRCNT_Pos (21U) -#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 */ -#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count */ +#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 +#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count #define GLPMCFG_SNDLPM_Pos (24U) -#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 */ -#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction */ +#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 +#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction #define GLPMCFG_LPMRCNTSTS_Pos (25U) -#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 */ -#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status */ +#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 +#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status #define GLPMCFG_ENBESL_Pos (28U) -#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 */ -#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency */ +#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 +#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency /******************** Bit definition for DIEPEACHMSK1 register ********************/ #define DIEPEACHMSK1_XFRCM_Pos (0U) -#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ -#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 +#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask #define DIEPEACHMSK1_EPDM_Pos (1U) -#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 */ -#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 +#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask #define DIEPEACHMSK1_TOM_Pos (3U) -#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 */ -#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 +#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) #define DIEPEACHMSK1_ITTXFEMSK_Pos (4U) -#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ -#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 +#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DIEPEACHMSK1_INEPNMM_Pos (5U) -#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ -#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 +#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask #define DIEPEACHMSK1_INEPNEM_Pos (6U) -#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ -#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 +#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask #define DIEPEACHMSK1_TXFURM_Pos (8U) -#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ -#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask */ +#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 +#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask #define DIEPEACHMSK1_BIM_Pos (9U) -#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 */ -#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 +#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask #define DIEPEACHMSK1_NAKM_Pos (13U) -#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 */ -#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ +#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 +#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask /******************** Bit definition for HPRT register ********************/ #define HPRT_PCSTS_Pos (0U) -#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 */ -#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status */ +#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 +#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status #define HPRT_PCDET_Pos (1U) -#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 */ -#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected */ +#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 +#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected #define HPRT_PENA_Pos (2U) -#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 */ -#define HPRT_PENA HPRT_PENA_Msk // Port enable */ +#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 +#define HPRT_PENA HPRT_PENA_Msk // Port enable #define HPRT_PENCHNG_Pos (3U) -#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 */ -#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change */ +#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 +#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change #define HPRT_POCA_Pos (4U) -#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 */ -#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active */ +#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 +#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active #define HPRT_POCCHNG_Pos (5U) -#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 */ -#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change */ +#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 +#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change #define HPRT_PRES_Pos (6U) -#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 */ -#define HPRT_PRES HPRT_PRES_Msk // Port resume */ +#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 +#define HPRT_PRES HPRT_PRES_Msk // Port resume #define HPRT_PSUSP_Pos (7U) -#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 */ -#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend */ +#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 +#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend #define HPRT_PRST_Pos (8U) -#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 */ -#define HPRT_PRST HPRT_PRST_Msk // Port reset */ +#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 +#define HPRT_PRST HPRT_PRST_Msk // Port reset #define HPRT_PLSTS_Pos (10U) -#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 */ -#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status */ -#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 */ -#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 */ +#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 +#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status +#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 +#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 #define HPRT_PPWR_Pos (12U) -#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 */ -#define HPRT_PPWR HPRT_PPWR_Msk // Port power */ +#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 +#define HPRT_PPWR HPRT_PPWR_Msk // Port power #define HPRT_PTCTL_Pos (13U) -#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 */ -#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control */ -#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 */ -#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 */ -#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 */ -#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 */ +#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 +#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control +#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 +#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 +#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 +#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 #define HPRT_PSPD_Pos (17U) -#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 */ -#define HPRT_PSPD HPRT_PSPD_Msk // Port speed */ -#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 */ -#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 */ +#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 +#define HPRT_PSPD HPRT_PSPD_Msk // Port speed +#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 +#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 /******************** Bit definition for DOEPEACHMSK1 register ********************/ #define DOEPEACHMSK1_XFRCM_Pos (0U) -#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ -#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 +#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask #define DOEPEACHMSK1_EPDM_Pos (1U) -#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 */ -#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 +#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask #define DOEPEACHMSK1_TOM_Pos (3U) -#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 */ -#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask */ +#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 +#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask #define DOEPEACHMSK1_ITTXFEMSK_Pos (4U) -#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ -#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 +#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DOEPEACHMSK1_INEPNMM_Pos (5U) -#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ -#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 +#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask #define DOEPEACHMSK1_INEPNEM_Pos (6U) -#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ -#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 +#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask #define DOEPEACHMSK1_TXFURM_Pos (8U) -#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ -#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask */ +#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 +#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask #define DOEPEACHMSK1_BIM_Pos (9U) -#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 */ -#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 +#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask #define DOEPEACHMSK1_BERRM_Pos (12U) -#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 */ -#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask */ +#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 +#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask #define DOEPEACHMSK1_NAKM_Pos (13U) -#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 */ -#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ +#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 +#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask #define DOEPEACHMSK1_NYETM_Pos (14U) -#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 */ -#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask */ +#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 +#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask /******************** Bit definition for HPTXFSIZ register ********************/ #define HPTXFSIZ_PTXSA_Pos (0U) -#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF */ -#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address */ +#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF +#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address #define HPTXFSIZ_PTXFD_Pos (16U) -#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 */ -#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth */ +#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 +#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth /******************** Bit definition for DIEPCTL register ********************/ #define DIEPCTL_MPSIZ_Pos (0U) -#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF */ -#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size */ +#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF +#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size #define DIEPCTL_USBAEP_Pos (15U) -#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 */ -#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint */ +#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 +#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint #define DIEPCTL_EONUM_DPID_Pos (16U) -#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 */ -#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame */ +#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 +#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame #define DIEPCTL_NAKSTS_Pos (17U) -#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 */ -#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status */ +#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 +#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status #define DIEPCTL_EPTYP_Pos (18U) -#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 */ -#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type */ -#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 */ -#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 +#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type +#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 +#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 #define DIEPCTL_STALL_Pos (21U) -#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 */ -#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake */ +#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 +#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake #define DIEPCTL_TXFNUM_Pos (22U) -#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 */ -#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number */ -#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 */ -#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 */ -#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 */ -#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 */ +#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 +#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number +#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 +#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 +#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 +#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 #define DIEPCTL_CNAK_Pos (26U) -#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 */ -#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK */ +#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 +#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK #define DIEPCTL_SNAK_Pos (27U) -#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 */ -#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK */ +#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 +#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK #define DIEPCTL_SD0PID_SEVNFRM_Pos (28U) -#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ -#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 +#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID #define DIEPCTL_SODDFRM_Pos (29U) -#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 */ -#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame */ +#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 +#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame #define DIEPCTL_EPDIS_Pos (30U) -#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 */ -#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable */ +#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 +#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable #define DIEPCTL_EPENA_Pos (31U) -#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 */ -#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable */ +#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 +#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for HCCHAR register ********************/ #define HCCHAR_MPSIZ_Pos (0U) -#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF */ -#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size */ +#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF +#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size #define HCCHAR_EPNUM_Pos (11U) -#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 */ -#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number */ -#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 */ -#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 */ -#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 */ -#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 */ +#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 +#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number +#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 +#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 +#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 +#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 #define HCCHAR_EPDIR_Pos (15U) -#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 */ -#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction */ +#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 +#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction #define HCCHAR_LSDEV_Pos (17U) -#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 */ -#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device */ +#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 +#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device #define HCCHAR_EPTYP_Pos (18U) -#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 */ -#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type */ -#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 */ -#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 */ +#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 +#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type +#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 +#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 #define HCCHAR_MC_Pos (20U) -#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 */ -#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) */ -#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 */ -#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 */ +#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 +#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) +#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 +#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 #define HCCHAR_DAD_Pos (22U) -#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 */ -#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address */ -#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 */ -#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 */ -#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 */ -#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 */ -#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 */ -#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 */ -#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 */ +#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 +#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address +#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 +#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 +#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 +#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 +#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 +#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 +#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 #define HCCHAR_ODDFRM_Pos (29U) -#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 */ -#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame */ +#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 +#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame #define HCCHAR_CHDIS_Pos (30U) -#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 */ -#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable */ +#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 +#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable #define HCCHAR_CHENA_Pos (31U) -#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 */ -#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable */ +#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 +#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable /******************** Bit definition for HCSPLT register ********************/ #define HCSPLT_PRTADDR_Pos (0U) -#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F */ -#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address */ -#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 */ -#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 */ -#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 */ -#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 */ -#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 */ -#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 */ -#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 */ +#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F +#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address +#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 +#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 +#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 +#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 +#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 +#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 +#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 #define HCSPLT_HUBADDR_Pos (7U) -#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 */ -#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address */ -#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 */ -#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 */ -#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 */ -#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 */ -#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 */ -#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 */ -#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 */ +#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 +#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address +#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 +#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 +#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 +#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 +#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 +#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 +#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 #define HCSPLT_XACTPOS_Pos (14U) -#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 */ -#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS */ -#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 */ -#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 */ +#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 +#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS +#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 +#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 #define HCSPLT_COMPLSPLT_Pos (16U) -#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 */ -#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split */ +#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 +#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split #define HCSPLT_SPLITEN_Pos (31U) -#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 */ -#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable */ +#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 +#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable /******************** Bit definition for HCINT register ********************/ #define HCINT_XFRC_Pos (0U) -#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 */ -#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed */ +#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 +#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed #define HCINT_CHH_Pos (1U) -#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 */ -#define HCINT_CHH HCINT_CHH_Msk // Channel halted */ +#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 +#define HCINT_CHH HCINT_CHH_Msk // Channel halted #define HCINT_AHBERR_Pos (2U) -#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 */ -#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error */ +#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 +#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error #define HCINT_STALL_Pos (3U) -#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 */ -#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt */ +#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 +#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt #define HCINT_NAK_Pos (4U) -#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 */ -#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt */ +#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 +#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt #define HCINT_ACK_Pos (5U) -#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 */ -#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt */ +#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 +#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt #define HCINT_NYET_Pos (6U) -#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 */ -#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt */ +#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 +#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt #define HCINT_TXERR_Pos (7U) -#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 */ -#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error */ +#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 +#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error #define HCINT_BBERR_Pos (8U) -#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 */ -#define HCINT_BBERR HCINT_BBERR_Msk // Babble error */ +#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 +#define HCINT_BBERR HCINT_BBERR_Msk // Babble error #define HCINT_FRMOR_Pos (9U) -#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 */ -#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun */ +#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 +#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun #define HCINT_DTERR_Pos (10U) -#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 */ -#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error */ +#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 +#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error /******************** Bit definition for DIEPINT register ********************/ #define DIEPINT_XFRC_Pos (0U) -#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 */ -#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 +#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt #define DIEPINT_EPDISD_Pos (1U) -#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 */ -#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 +#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt #define DIEPINT_AHBERR_Pos (2U) -#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 */ -#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction */ +#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 +#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction #define DIEPINT_TOC_Pos (3U) -#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 */ -#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition */ +#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 +#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition #define DIEPINT_ITTXFE_Pos (4U) -#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 */ -#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty */ +#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 +#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty #define DIEPINT_INEPNM_Pos (5U) -#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 */ -#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch */ +#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 +#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch #define DIEPINT_INEPNE_Pos (6U) -#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 */ -#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective */ +#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 +#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective #define DIEPINT_TXFE_Pos (7U) -#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 */ -#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty */ +#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 +#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty #define DIEPINT_TXFIFOUDRN_Pos (8U) -#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 */ -#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun */ +#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 +#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun #define DIEPINT_BNA_Pos (9U) -#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 */ -#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt */ +#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 +#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt #define DIEPINT_PKTDRPSTS_Pos (11U) -#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 */ -#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status */ +#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 +#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status #define DIEPINT_BERR_Pos (12U) -#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 */ -#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt */ +#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 +#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt #define DIEPINT_NAK_Pos (13U) -#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 */ -#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt */ +#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 +#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt /******************** Bit definition for HCINTMSK register ********************/ #define HCINTMSK_XFRCM_Pos (0U) -#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 */ -#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask */ +#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 +#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask #define HCINTMSK_CHHM_Pos (1U) -#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 */ -#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask */ +#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 +#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask #define HCINTMSK_AHBERR_Pos (2U) -#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 */ -#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error */ +#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 +#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error #define HCINTMSK_STALLM_Pos (3U) -#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 */ -#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask */ +#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 +#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask #define HCINTMSK_NAKM_Pos (4U) -#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 */ -#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask */ +#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 +#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask #define HCINTMSK_ACKM_Pos (5U) -#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 */ -#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask */ +#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 +#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask #define HCINTMSK_NYET_Pos (6U) -#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 */ -#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask */ +#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 +#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask #define HCINTMSK_TXERRM_Pos (7U) -#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 */ -#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask */ +#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 +#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask #define HCINTMSK_BBERRM_Pos (8U) -#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 */ -#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask */ +#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 +#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask #define HCINTMSK_FRMORM_Pos (9U) -#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 */ -#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask */ +#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 +#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask #define HCINTMSK_DTERRM_Pos (10U) -#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 */ -#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask */ +#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 +#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask /******************** Bit definition for DIEPTSIZ register ********************/ #define DIEPTSIZ_XFRSIZ_Pos (0U) -#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size #define DIEPTSIZ_PKTCNT_Pos (19U) -#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count */ +#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count #define DIEPTSIZ_MULCNT_Pos (29U) -#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 */ -#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count */ +#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 +#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count /******************** Bit definition for HCTSIZ register ********************/ #define HCTSIZ_XFRSIZ_Pos (0U) -#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size */ +#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size #define HCTSIZ_PKTCNT_Pos (19U) -#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count */ +#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count #define HCTSIZ_DOPING_Pos (31U) -#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 */ -#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING */ +#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 +#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING #define HCTSIZ_DPID_Pos (29U) -#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 */ -#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID */ -#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 */ -#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 */ +#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 +#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID +#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 +#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 /******************** Bit definition for DIEPDMA register ********************/ #define DIEPDMA_DMAADDR_Pos (0U) -#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF */ -#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address */ +#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF +#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address /******************** Bit definition for HCDMA register ********************/ #define HCDMA_DMAADDR_Pos (0U) -#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF */ -#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address */ +#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF +#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address /******************** Bit definition for DTXFSTS register ********************/ #define DTXFSTS_INEPTFSAV_Pos (0U) -#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF */ -#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available */ +#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF +#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available /******************** Bit definition for DIEPTXF register ********************/ #define DIEPTXF_INEPTXSA_Pos (0U) -#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF */ -#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address */ +#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF +#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address #define DIEPTXF_INEPTXFD_Pos (16U) -#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 */ -#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth */ +#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 +#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth /******************** Bit definition for DOEPCTL register ********************/ #define DOEPCTL_MPSIZ_Pos (0U) -#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF */ -#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size */ //Bit 1 */ +#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF +#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size //Bit 1 #define DOEPCTL_USBAEP_Pos (15U) -#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 */ -#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint */ +#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 +#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint #define DOEPCTL_NAKSTS_Pos (17U) -#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 */ -#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status */ +#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 +#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status #define DOEPCTL_SD0PID_SEVNFRM_Pos (28U) -#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ -#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 +#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID #define DOEPCTL_SODDFRM_Pos (29U) -#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 */ -#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame */ +#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 +#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame #define DOEPCTL_EPTYP_Pos (18U) -#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 */ -#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type */ -#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 */ -#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 +#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type +#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 +#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 #define DOEPCTL_SNPM_Pos (20U) -#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 */ -#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode */ +#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 +#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode #define DOEPCTL_STALL_Pos (21U) -#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 */ -#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake */ +#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 +#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake #define DOEPCTL_CNAK_Pos (26U) -#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 */ -#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK */ +#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 +#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK #define DOEPCTL_SNAK_Pos (27U) -#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 */ -#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK */ +#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 +#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK #define DOEPCTL_EPDIS_Pos (30U) -#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 */ -#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable */ +#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 +#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable #define DOEPCTL_EPENA_Pos (31U) -#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 */ -#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable */ +#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 +#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for DOEPINT register ********************/ #define DOEPINT_XFRC_Pos (0U) -#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 */ -#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 +#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt #define DOEPINT_EPDISD_Pos (1U) -#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 */ -#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 +#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt #define DOEPINT_AHBERR_Pos (2U) -#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 */ -#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction */ +#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 +#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction #define DOEPINT_STUP_Pos (3U) -#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 */ -#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done */ +#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 +#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done #define DOEPINT_OTEPDIS_Pos (4U) -#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 */ -#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled */ +#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 +#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled #define DOEPINT_OTEPSPR_Pos (5U) -#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 */ -#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write */ +#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 +#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write #define DOEPINT_B2BSTUP_Pos (6U) -#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 */ -#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received */ +#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 +#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received #define DOEPINT_OUTPKTERR_Pos (8U) -#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 */ -#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error */ +#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 +#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error #define DOEPINT_NAK_Pos (13U) -#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 */ -#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device */ +#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 +#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device #define DOEPINT_NYET_Pos (14U) -#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 */ -#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt */ +#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 +#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt #define DOEPINT_STPKTRX_Pos (15U) -#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 */ -#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received */ +#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 +#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received /******************** Bit definition for DOEPTSIZ register ********************/ #define DOEPTSIZ_XFRSIZ_Pos (0U) -#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size #define DOEPTSIZ_PKTCNT_Pos (19U) -#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count */ +#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count #define DOEPTSIZ_STUPCNT_Pos (29U) -#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 */ -#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count */ -#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 */ -#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 */ +#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 +#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count +#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 +#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 /******************** Bit definition for PCGCTL register ********************/ #define PCGCTL_IF_DEV_MODE TU_BIT(31) diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_xmc.h b/test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_xmc.h similarity index 100% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_xmc.h rename to test-devices/composite-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_xmc.h diff --git a/test-devices/composite-stm32/lib/tinyusb/tusb.c b/test-devices/composite-stm32/lib/tinyusb/tusb.c index 85fe5a3c..0092267a 100644 --- a/test-devices/composite-stm32/lib/tinyusb/tusb.c +++ b/test-devices/composite-stm32/lib/tinyusb/tusb.c @@ -36,39 +36,37 @@ #endif #if CFG_TUH_ENABLED -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #endif //--------------------------------------------------------------------+ // Public API //--------------------------------------------------------------------+ -bool tusb_init(void) -{ -#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) +bool tusb_init(void) { + #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) // init device stack CFG_TUSB_RHPORTx_MODE must be defined TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); -#endif + #endif -#if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT) + #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT) // init host stack CFG_TUSB_RHPORTx_MODE must be defined TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); -#endif + #endif return true; } -bool tusb_inited(void) -{ +bool tusb_inited(void) { bool ret = false; -#if CFG_TUD_ENABLED + #if CFG_TUD_ENABLED ret = ret || tud_inited(); -#endif + #endif -#if CFG_TUH_ENABLED + #if CFG_TUH_ENABLED ret = ret || tuh_inited(); -#endif + #endif return ret; } @@ -77,43 +75,35 @@ bool tusb_inited(void) // Descriptor helper //--------------------------------------------------------------------+ -uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) -{ - while(desc+1 < end) - { - if ( desc[1] == byte1 ) return desc; +uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) { + while (desc + 1 < end) { + if (desc[1] == byte1) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } -uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) -{ - while(desc+2 < end) - { - if ( desc[1] == byte1 && desc[2] == byte2) return desc; +uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) { + while (desc + 2 < end) { + if (desc[1] == byte1 && desc[2] == byte2) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } -uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) -{ - while(desc+3 < end) - { +uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) { + while (desc + 3 < end) { if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } - //--------------------------------------------------------------------+ // Endpoint Helper for both Host and Device stack //--------------------------------------------------------------------+ -bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) -{ +bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; // pre-check to help reducing mutex lock @@ -122,111 +112,93 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) // can only claim the endpoint if it is not busy and not claimed yet. bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0); - if (available) - { + if (available) { ep_state->claimed = 1; } (void) osal_mutex_unlock(mutex); - return available; } -bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) -{ +bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; - (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only release the endpoint if it is claimed and not busy bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0); - if (ret) - { + if (ret) { ep_state->claimed = 0; } (void) osal_mutex_unlock(mutex); - return ret; } -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) -{ +bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { + switch (desc_ep->bmAttributes.xfer) { + case TUSB_XFER_ISOCHRONOUS: { uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); TU_ASSERT(max_packet_size <= spec_size); + break; } - break; case TUSB_XFER_BULK: - if (speed == TUSB_SPEED_HIGH) - { + if (speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 TU_ASSERT(max_packet_size == 512); - }else - { + } else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 TU_ASSERT(max_packet_size <= 64); } - break; + break; - case TUSB_XFER_INTERRUPT: - { + case TUSB_XFER_INTERRUPT: { uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); TU_ASSERT(max_packet_size <= spec_size); + break; } - break; - default: return false; + default: + return false; } return true; } -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) -{ +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, + uint8_t driver_id) { uint8_t const* p_desc = (uint8_t const*) desc_itf; uint8_t const* desc_end = p_desc + desc_len; - while( p_desc < desc_end ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { + while (p_desc < desc_end) { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - p_desc = tu_desc_next(p_desc); } } -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) { uint8_t const* p_desc = (uint8_t const*) desc_itf; uint16_t len = 0; - while (itf_count--) - { + while (itf_count--) { // Next on interface desc len += tu_desc_len(desc_itf); p_desc = tu_desc_next(p_desc); - while (len < max_len) - { + while (len < max_len) { // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) - { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { + return len; + } + if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0) { break; } @@ -243,9 +215,8 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, //--------------------------------------------------------------------+ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, - void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) -{ - osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex); + void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) { + osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef); (void) new_mutex; (void) is_tx; @@ -259,92 +230,82 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } +bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { + (void) s; + #if OSAL_MUTEX_REQUIRED + if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr); + if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd); + #endif + return true; +} + TU_ATTR_ALWAYS_INLINE static inline -bool stream_claim(tu_edpt_stream_t* s) -{ - if (s->is_host) - { +bool stream_claim(tu_edpt_stream_t* s) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_claim(s->daddr, s->ep_addr); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_claim(s->rhport, s->ep_addr); #endif } - return false; } TU_ATTR_ALWAYS_INLINE static inline -bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) -{ - if (s->is_host) - { +bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_xfer(s->daddr, s->ep_addr, count ? s->ep_buf : NULL, count); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_xfer(s->rhport, s->ep_addr, count ? s->ep_buf : NULL, count); #endif } - return false; } TU_ATTR_ALWAYS_INLINE static inline -bool stream_release(tu_edpt_stream_t* s) -{ - if (s->is_host) - { +bool stream_release(tu_edpt_stream_t* s) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_release(s->daddr, s->ep_addr); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_release(s->rhport, s->ep_addr); #endif } - return false; } //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ - -bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) -{ +bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size - TU_VERIFY( !tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize-1))) ); - - TU_VERIFY( stream_claim(s) ); - TU_ASSERT( stream_xfer(s, 0) ); - + TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize - 1)))); + TU_VERIFY(stream_claim(s)); + TU_ASSERT(stream_xfer(s, 0)); return true; } -uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) { // skip if no data - TU_VERIFY( tu_fifo_count(&s->ff), 0 ); + TU_VERIFY(tu_fifo_count(&s->ff), 0); // Claim the endpoint - TU_VERIFY( stream_claim(s), 0 ); + TU_VERIFY(stream_claim(s), 0); // Pull data from FIFO -> EP buf uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); - if ( count ) - { - TU_ASSERT( stream_xfer(s, count), 0 ); + if (count) { + TU_ASSERT(stream_xfer(s, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer // Note: data is dropped if terminal is not connected stream_release(s); @@ -352,16 +313,13 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) } } -uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize) -{ +uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) { TU_VERIFY(bufsize); // TODO support ZLP - uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); // flush if fifo has more than packet size or // in rare case: fifo depth is configured too small (which never reach packet size) - if ( (tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize) ) - { + if ((tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize)) { tu_edpt_stream_write_xfer(s); } @@ -371,9 +329,7 @@ uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ - -uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) { uint16_t available = tu_fifo_remaining(&s->ff); // Prepare for incoming data but only allow what we can store in the ring buffer. @@ -388,25 +344,21 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) // get available again since fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&s->ff); - if ( available >= s->ep_packetsize ) - { + if (available >= s->ep_packetsize) { // multiple of packet size limit by ep bufsize - uint16_t count = (uint16_t) (available & ~(s->ep_packetsize -1)); + uint16_t count = (uint16_t) (available & ~(s->ep_packetsize - 1)); count = tu_min16(count, s->ep_bufsize); - TU_ASSERT( stream_xfer(s, count), 0 ); - + TU_ASSERT(stream_xfer(s, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer stream_release(s); return 0; } } -uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) -{ +uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); tu_edpt_stream_read_xfer(s); return num_read; @@ -419,39 +371,36 @@ uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize #if CFG_TUSB_DEBUG #include -#if CFG_TUSB_DEBUG >= 2 - -char const* const tu_str_speed[] = { "Full", "Low", "High" }; -char const* const tu_str_std_request[] = -{ - "Get Status" , - "Clear Feature" , - "Reserved" , - "Set Feature" , - "Reserved" , - "Set Address" , - "Get Descriptor" , - "Set Descriptor" , - "Get Configuration" , - "Set Configuration" , - "Get Interface" , - "Set Interface" , - "Synch Frame" +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL +char const* const tu_str_speed[] = {"Full", "Low", "High"}; +char const* const tu_str_std_request[] = { + "Get Status", + "Clear Feature", + "Reserved", + "Set Feature", + "Reserved", + "Set Address", + "Get Descriptor", + "Set Descriptor", + "Get Configuration", + "Set Configuration", + "Get Interface", + "Set Interface", + "Synch Frame" }; +char const* const tu_str_xfer_result[] = { + "OK", "FAILED", "STALLED", "TIMEOUT" +}; #endif -static void dump_str_line(uint8_t const* buf, uint16_t count) -{ +static void dump_str_line(uint8_t const* buf, uint16_t count) { tu_printf(" |"); - // each line is 16 bytes - for(uint16_t i=0; i= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x @@ -119,7 +132,9 @@ // NXP Kinetis #define OPT_MCU_KINETIS_KL 1200 ///< NXP KL series -#define OPT_MCU_KINETIS_K32 1201 ///< NXP K32 series +#define OPT_MCU_KINETIS_K32L 1201 ///< NXP K32L series +#define OPT_MCU_KINETIS_K32 1201 ///< Alias to K32L +#define OPT_MCU_KINETIS_K 1202 ///< NXP K series #define OPT_MCU_MKL25ZXX 1200 ///< Alias to KL (obsolete) #define OPT_MCU_K32L2BXX 1201 ///< Alias to K32 (obsolete) @@ -133,7 +148,6 @@ #define OPT_MCU_RX72N 1402 ///< Renesas RX72N #define OPT_MCU_RAXXX 1403 ///< Renesas RAxxx families - // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 @@ -165,11 +179,17 @@ // WCH #define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 +#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x + -// Helper to check if configured MCU is one of listed +// NXP LPC MCX +#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series +#define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series + +// Check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input -#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) -#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) +#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) +#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) //--------------------------------------------------------------------+ // Supported OS @@ -274,7 +294,7 @@ // In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler // to generate unaligned access code. // LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM -#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) +#if TUD_OPT_HIGH_SPEED && TU_CHECK_MCU(OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX) #define TUP_MCU_STRICT_ALIGN 1 #else #define TUP_MCU_STRICT_ALIGN 0 @@ -290,15 +310,24 @@ #define CFG_TUSB_DEBUG 0 #endif -// TODO MEM_SECTION can be different for host and device controller -// should use CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION +// Level where CFG_TUSB_DEBUG must be at least for USBH is logged +#ifndef CFG_TUH_LOG_LEVEL + #define CFG_TUH_LOG_LEVEL 2 +#endif + +// Level where CFG_TUSB_DEBUG must be at least for USBD is logged +#ifndef CFG_TUD_LOG_LEVEL + #define CFG_TUD_LOG_LEVEL 2 +#endif + +// Memory section for placing buffer used for usb transferring. If MEM_SECTION is different for +// host and device use: CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION instead #ifndef CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_SECTION #endif -// alignment requirement of buffer used for endpoint transferring -// TODO MEM_ALIGN can be different for host and device controller -// should use CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN +// Alignment requirement of buffer used for usb transferring. if MEM_ALIGN is different for +// host and device controller use: CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN instead #ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif @@ -316,24 +345,14 @@ // Device Options (Default) //-------------------------------------------------------------------- -// Attribute to place data in accessible RAM for device controller -// default to CFG_TUSB_MEM_SECTION for backward-compatible +// Attribute to place data in accessible RAM for device controller (default: CFG_TUSB_MEM_SECTION) #ifndef CFG_TUD_MEM_SECTION - #ifdef CFG_TUSB_MEM_SECTION - #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION - #else - #define CFG_TUD_MEM_SECTION - #endif + #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION #endif -// Attribute to align memory for device controller -// default to CFG_TUSB_MEM_ALIGN for backward-compatible +// Attribute to align memory for device controller (default: CFG_TUSB_MEM_ALIGN) #ifndef CFG_TUD_MEM_ALIGN - #ifdef CFG_TUSB_MEM_ALIGN - #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN - #else - #define CFG_TUD_MEM_ALIGN TU_ATTR_ALIGNED(4) - #endif + #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN #endif #ifndef CFG_TUD_ENDPOINT0_SIZE @@ -344,6 +363,15 @@ #define CFG_TUD_INTERFACE_MAX 16 #endif +//------------- Device Class Driver -------------// +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + +#if CFG_TUD_BTH && !defined(CFG_TUD_BTH_ISO_ALT_COUNT) +#error CFG_TUD_BTH_ISO_ALT_COUNT must be defined to tell Bluetooth driver the number of ISO endpoints to use +#endif + #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif @@ -384,10 +412,6 @@ #define CFG_TUD_DFU 0 #endif -#ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 -#endif - #ifndef CFG_TUD_ECM_RNDIS #ifdef CFG_TUD_NET #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" @@ -414,29 +438,24 @@ #endif #endif // CFG_TUH_ENABLED -// Attribute to place data in accessible RAM for host controller -// default to CFG_TUSB_MEM_SECTION for backward-compatible +// Attribute to place data in accessible RAM for host controller (default: CFG_TUSB_MEM_SECTION) #ifndef CFG_TUH_MEM_SECTION - #ifdef CFG_TUSB_MEM_SECTION - #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION - #else - #define CFG_TUH_MEM_SECTION - #endif + #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION #endif // Attribute to align memory for host controller #ifndef CFG_TUH_MEM_ALIGN - #define CFG_TUH_MEM_ALIGN TU_ATTR_ALIGNED(4) + #define CFG_TUH_MEM_ALIGN CFG_TUSB_MEM_ALIGN #endif //------------- CLASS -------------// #ifndef CFG_TUH_HUB -#define CFG_TUH_HUB 0 + #define CFG_TUH_HUB 0 #endif #ifndef CFG_TUH_CDC -#define CFG_TUH_CDC 0 + #define CFG_TUH_CDC 0 #endif #ifndef CFG_TUH_CDC_FTDI @@ -444,40 +463,85 @@ #define CFG_TUH_CDC_FTDI 0 #endif +#ifndef CFG_TUH_CDC_FTDI_VID_PID_LIST + // List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID + #define CFG_TUH_CDC_FTDI_VID_PID_LIST \ + {0x0403, 0x6001}, {0x0403, 0x6006}, {0x0403, 0x6010}, {0x0403, 0x6011}, \ + {0x0403, 0x6014}, {0x0403, 0x6015}, {0x0403, 0x8372}, {0x0403, 0xFBFA}, \ + {0x0403, 0xCD18} +#endif + #ifndef CFG_TUH_CDC_CP210X // CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 0 #endif +#ifndef CFG_TUH_CDC_CP210X_VID_PID_LIST + // List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID + #define CFG_TUH_CDC_CP210X_VID_PID_LIST \ + {0x10C4, 0xEA60}, {0x10C4, 0xEA70} +#endif + +#ifndef CFG_TUH_CDC_CH34X + // CH34X is not part of CDC class, only to re-use CDC driver API + #define CFG_TUH_CDC_CH34X 0 +#endif + +#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST + // List of product IDs that can use the CH34X CDC driver + #define CFG_TUH_CDC_CH34X_VID_PID_LIST \ + { 0x1a86, 0x5523 }, /* ch341 chip */ \ + { 0x1a86, 0x7522 }, /* ch340k chip */ \ + { 0x1a86, 0x7523 }, /* ch340 chip */ \ + { 0x1a86, 0xe523 }, /* ch330 chip */ \ + { 0x4348, 0x5523 }, /* ch340 custom chip */ \ + { 0x2184, 0x0057 }, /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ \ + { 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ +#endif + #ifndef CFG_TUH_HID -#define CFG_TUH_HID 0 + #define CFG_TUH_HID 0 #endif #ifndef CFG_TUH_MIDI -#define CFG_TUH_MIDI 0 + #define CFG_TUH_MIDI 0 #endif #ifndef CFG_TUH_MSC -#define CFG_TUH_MSC 0 + #define CFG_TUH_MSC 0 #endif #ifndef CFG_TUH_VENDOR -#define CFG_TUH_VENDOR 0 + #define CFG_TUH_VENDOR 0 #endif #ifndef CFG_TUH_API_EDPT_XFER -#define CFG_TUH_API_EDPT_XFER 0 + #define CFG_TUH_API_EDPT_XFER 0 #endif // Enable PIO-USB software host controller #ifndef CFG_TUH_RPI_PIO_USB -#define CFG_TUH_RPI_PIO_USB 0 + #define CFG_TUH_RPI_PIO_USB 0 #endif #ifndef CFG_TUD_RPI_PIO_USB -#define CFG_TUD_RPI_PIO_USB 0 + #define CFG_TUD_RPI_PIO_USB 0 #endif +// MAX3421 Host controller option +#ifndef CFG_TUH_MAX3421 + #define CFG_TUH_MAX3421 0 +#endif + +//--------------------------------------------------------------------+ +// TypeC Options (Default) +//--------------------------------------------------------------------+ + +#ifndef CFG_TUC_ENABLED +#define CFG_TUC_ENABLED 0 + +#define tuc_int_handler(_p) +#endif //------------------------------------------------------------------ // Configuration Validation diff --git a/test-devices/composite-stm32/platformio.ini b/test-devices/composite-stm32/platformio.ini index d0c31313..0a2fda29 100644 --- a/test-devices/composite-stm32/platformio.ini +++ b/test-devices/composite-stm32/platformio.ini @@ -2,7 +2,9 @@ tinyusb_flags = -D CFG_TUD_CDC=1 -D CFG_VENDOR_ADVANCED=1 + -D CFG_VENDOR_ADVANCED_NUM_INTF=2 -D CFG_TUSB_RHPORT1_MODE=OPT_MODE_NONE + -D CFG_WINUSB=OPT_WINUSB_MSOS20 platform = ststm32 framework = cmsis debug_tool = stlink diff --git a/test-devices/composite-stm32/src/board_f1.c b/test-devices/composite-stm32/src/board_f1.c index e3dc0eb5..344cae68 100644 --- a/test-devices/composite-stm32/src/board_f1.c +++ b/test-devices/composite-stm32/src/board_f1.c @@ -188,20 +188,16 @@ uint32_t board_millis(void) { void board_led_write(bool on) { if (on) - gpio_set(GPIOB, 12); - else gpio_clear(GPIOB, 12); + else + gpio_set(GPIOB, 12); } // --- Interrupt handlers --- void SysTick_Handler (void) { - millis_count++; -} - -void USBWakeUp_IRQHandler(void) { - tud_int_handler(0); + millis_count++; } void USB_HP_IRQHandler(void) { diff --git a/test-devices/composite-stm32/src/board_f4.c b/test-devices/composite-stm32/src/board_f4.c index 6f83803f..927320d5 100644 --- a/test-devices/composite-stm32/src/board_f4.c +++ b/test-devices/composite-stm32/src/board_f4.c @@ -262,16 +262,16 @@ uint32_t board_millis(void) { void board_led_write(bool on) { if (on) - gpio_set(GPIOC, 13); - else gpio_clear(GPIOC, 13); + else + gpio_set(GPIOC, 13); } // --- Interrupt handlers --- void SysTick_Handler (void) { - millis_count++; + millis_count++; } void OTG_FS_IRQHandler(void) { diff --git a/test-devices/composite-stm32/src/main.c b/test-devices/composite-stm32/src/main.c index 10f12572..0259b140 100644 --- a/test-devices/composite-stm32/src/main.c +++ b/test-devices/composite-stm32/src/main.c @@ -21,19 +21,21 @@ // FIFO buffer for loopback data tu_fifo_t loopback_fifo; uint8_t loopback_buffer[512]; +bool delay_loopback_reset = false; // RX buffer for loopback uint8_t loopback_rx_buffer[64]; -// Blink durations -enum { - BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, -}; +static bool is_blinking = true; +static uint32_t led_on_until = 0; +static uint32_t blink_toogle_at = 0; +static bool is_blink_on = true; -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +static inline bool has_expired(uint32_t deadline, uint32_t now) { + return (int32_t)(now - deadline) >= 0; +} +static void led_busy(void); static void led_blinking_task(void); static void cdc_task(void); static void loopback_init(void); @@ -61,7 +63,11 @@ int main(void) { // reset device in predictable state void reset_buffers(void) { - tu_fifo_clear(&loopback_fifo); + if (cust_vendor_is_transmitting(EP_LOOPBACK_TX)) { + delay_loopback_reset = true; + } else { + tu_fifo_clear(&loopback_fifo); + } } // --- Loopback @@ -73,6 +79,11 @@ void loopback_init(void) { // Check if the next transmission should be started void loopback_check_tx(void) { + if (delay_loopback_reset) { + tu_fifo_clear(&loopback_fifo); + delay_loopback_reset = false; + } + tu_fifo_buffer_info_t info; tu_fifo_get_read_info(&loopback_fifo, &info); @@ -82,6 +93,7 @@ void loopback_check_tx(void) { n = 128; cust_vendor_start_transmit(EP_LOOPBACK_TX, info.ptr_lin, n); + led_busy(); } } @@ -105,6 +117,7 @@ void cdc_task(void) { tud_cdc_write(buf, n); tud_cdc_write_flush(); + led_busy(); } @@ -115,15 +128,11 @@ void cust_vendor_rx_cb(uint8_t ep_addr, uint32_t recv_bytes) { tu_fifo_write_n(&loopback_fifo, loopback_rx_buffer, recv_bytes); loopback_check_rx(); loopback_check_tx(); + led_busy(); } // Invoked when last tx transfer finished void cust_vendor_tx_cb(uint8_t ep_addr, uint32_t sent_bytes) { - // If buffer has been reset in the mean time, - // we might not be able to advance it fully or at all. - int max_advance = tu_fifo_count(&loopback_fifo); - if (sent_bytes > max_advance) - sent_bytes = max_advance; if (sent_bytes > 0) tu_fifo_advance_read_pointer(&loopback_fifo, sent_bytes); @@ -131,14 +140,18 @@ void cust_vendor_tx_cb(uint8_t ep_addr, uint32_t sent_bytes) { loopback_check_rx(); // check ZLP - if ((sent_bytes & (BULK_MAX_PACKET_SIZE - 1)) == 0 + if (sent_bytes > 0 + && (sent_bytes & (BULK_MAX_PACKET_SIZE - 1)) == 0 && !cust_vendor_is_transmitting(ep_addr)) cust_vendor_start_transmit(EP_LOOPBACK_TX, NULL, 0); + + led_busy(); } // Invoked when interface has been opened void cust_vendor_intf_open_cb(uint8_t intf) { loopback_check_rx(); + led_busy(); } void cust_vendor_halt_cleared_cb(uint8_t ep_addr) { @@ -152,11 +165,18 @@ void cust_vendor_halt_cleared_cb(uint8_t ep_addr) { default: break; } + led_busy(); } // --- Control messages (see README) +#define REQUEST_SAVE_VALUE 0x01 +#define REQUEST_SAVE_DATA 0x02 +#define REQUEST_SEND_DATA 0x03 +#define REQUEST_RESET_BUFFERS 0x04 +#define REQUEST_GET_INTF_NUM 0x05 + static uint32_t saved_value = 0; bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { @@ -168,35 +188,51 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ switch (request->bRequest) { - case 0x01: + case REQUEST_SAVE_VALUE: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) { + led_busy(); // save value from wValue saved_value = request->wValue; return tud_control_status(rhport, request); } break; - case 0x02: + case REQUEST_SAVE_DATA: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 4) { + led_busy(); // receive into `saved_value` return tud_control_xfer(rhport, request, &saved_value, 4); } break; - case 0x03: + case REQUEST_SEND_DATA: if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 4) { + led_busy(); // transmit from `saved_value` return tud_control_xfer(rhport, request, &saved_value, 4); } break; - case 0x04: + case REQUEST_RESET_BUFFERS: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) { + led_busy(); reset_buffers(); return tud_control_status(rhport, request); } break; + case REQUEST_GET_INTF_NUM: + if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 1) { + uint8_t intf_num = request->wIndex & 0xff; + if (intf_num < 4) { + led_busy(); + // return inteface number + return tud_control_xfer(rhport, request, &intf_num, 1); + } + } + break; + +#if CFG_WINUSB == OPT_WINUSB_MSOS20 case MSOS_VENDOR_CODE: if (request->wIndex == 7) { // Get Microsoft OS 2.0 compatible descriptor @@ -205,6 +241,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ return tud_control_xfer(rhport, request, (uint8_t*) desc_ms_os_20, total_len); } break; +#endif default: break; @@ -229,38 +266,27 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) { // Invoked when device is mounted void tud_mount_cb(void) { - blink_interval_ms = BLINK_MOUNTED; + is_blinking = false; } -// Invoked when device is unmounted -void tud_umount_cb(void) { - blink_interval_ms = BLINK_NOT_MOUNTED; -} -// Invoked when usb bus is suspended -// remote_wakeup_en: if host allow us to perform remote wakeup -// Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) { - (void) remote_wakeup_en; - blink_interval_ms = BLINK_SUSPENDED; -} +// --- LED blinking --- -// Invoked when usb bus is resumed -void tud_resume_cb(void) { - blink_interval_ms = BLINK_MOUNTED; +void led_busy(void) { + led_on_until = board_millis() + 100; + board_led_write(true); } -// --- LED blinking --- - void led_blinking_task(void) { - static uint32_t start_ms = 0; - static bool led_state = false; - - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) - return; // not enough time - start_ms += blink_interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle + uint32_t now = board_millis(); + if (is_blinking) { + if (has_expired(blink_toogle_at, now)) { + is_blink_on = !is_blink_on; + blink_toogle_at = now + 250; + } + board_led_write(is_blink_on && (now & 7) == 0); + + } else if (has_expired(led_on_until, now)) { + board_led_write((now & 3) == 0); + } } diff --git a/test-devices/composite-stm32/src/usb_descriptors.c b/test-devices/composite-stm32/src/usb_descriptors.c index 25b8f78c..f45bfa1d 100644 --- a/test-devices/composite-stm32/src/usb_descriptors.c +++ b/test-devices/composite-stm32/src/usb_descriptors.c @@ -49,20 +49,17 @@ uint8_t const* tud_descriptor_device_cb(void) { // --- Configuration Descriptor --- -enum { - INTF_CDC_COMM = 0, - INTF_CDC_DATA, - INTF_LOOPBACK, - INTF_NUM_TOTAL -}; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + 9 + 7 + 7) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + 8 + 9 + 9 + 7 + 7) uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, INTF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 500), // CDC interfaces TUD_CDC_DESCRIPTOR(INTF_CDC_COMM, 0, EP_CDC_COMM, 8, EP_CDC_DATA_RX, EP_CDC_DATA_TX, BULK_MAX_PACKET_SIZE), + // Interface association descriptor (IAD) + CUSTOM_VENDOR_INTERFACE_ASSOCIATION(INTF_LOOPBACK_CTRL, 2, 0x04), + // Echo interface (no endpoint, just control messages) + CUSTOM_VENDOR_INTERFACE(INTF_LOOPBACK_CTRL, 0), // Loopback interface CUSTOM_VENDOR_INTERFACE(INTF_LOOPBACK, 2), // Loopback endpoint OUT @@ -82,6 +79,8 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t configuration_index) { // --- BOS Descriptor --- +#if CFG_WINUSB == OPT_WINUSB_MSOS20 + #define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) #define MS_OS_20_DESC_LEN 0xB2 @@ -108,7 +107,7 @@ uint8_t const desc_ms_os_20[] = { U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A), // Function Subset header: length, type, first interface, reserved, subset length - U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), INTF_LOOPBACK, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08), + U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), INTF_LOOPBACK_CTRL, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08), // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, @@ -129,6 +128,7 @@ uint8_t const desc_ms_os_20[] = { TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size"); +#endif // --- String Descriptors --- @@ -138,7 +138,8 @@ const char* const string_table[] = { 0, // 0 - supported languages (see below) "JavaDoesUSB", // 1 - manufacturer "Composite", // 2 - product - board_serial_num // 3 - serial number + board_serial_num, // 3 - serial number + "Loopback IAD" // 4 - interface association descriptor }; diff --git a/test-devices/composite-stm32/src/usb_descriptors.h b/test-devices/composite-stm32/src/usb_descriptors.h index 32edc120..1d6474c3 100644 --- a/test-devices/composite-stm32/src/usb_descriptors.h +++ b/test-devices/composite-stm32/src/usb_descriptors.h @@ -13,6 +13,24 @@ #include +#define OPT_WINUSB_NONE 0 +#define OPT_WINUSB_MSOS20 2 + +#ifndef CFG_WINUSB +#define CFG_WINUSB OPT_WINUSB_MSOS20 +#endif + + +// interfaces +enum { + INTF_CDC_COMM = 0, + INTF_CDC_DATA, + INTF_LOOPBACK_CTRL, + INTF_LOOPBACK, + INTF_NUM_TOTAL +}; + + #define INTR_MAX_PACKET_SIZE 16 #define BULK_MAX_PACKET_SIZE 64 @@ -24,8 +42,11 @@ #define EP_LOOPBACK_RX 0x01 #define EP_LOOPBACK_TX 0x82 -#define MSOS_VENDOR_CODE 0x44 +#if CFG_WINUSB == OPT_WINUSB_MSOS20 +#define MSOS_VENDOR_CODE 0x44 extern uint8_t const desc_ms_os_20[]; +#endif + void usb_init_serial_num(); diff --git a/test-devices/composite-stm32/src/vendor_custom.c b/test-devices/composite-stm32/src/vendor_custom.c index 36fe96ed..98c6c399 100644 --- a/test-devices/composite-stm32/src/vendor_custom.c +++ b/test-devices/composite-stm32/src/vendor_custom.c @@ -42,27 +42,30 @@ void cv_reset(uint8_t rhport) { // nothing to do } -uint16_t cv_open(uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len) { - +uint16_t cv_open(uint8_t rhport, tusb_desc_interface_t const *desc_intf, uint16_t max_len) { // return 0 if interface class is not "vendor specific" TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_intf->bInterfaceClass, 0); - uint8_t const * p_desc = tu_desc_next(desc_intf); - uint8_t const * desc_end = p_desc + max_len; - int num_endpoints = desc_intf->bNumEndpoints; + uint8_t const *p_desc = (uint8_t const *)desc_intf; + uint8_t const *p_end = p_desc + max_len; + + for (int i = 0; i < CFG_VENDOR_ADVANCED_NUM_INTF; i++) { + TU_VERIFY(p_desc + sizeof(tusb_desc_interface_t) <= p_end, 0); + + tusb_desc_interface_t const *intf = (tusb_desc_interface_t const *)p_desc; + int num_endpoints = intf->bNumEndpoints; - // iterate all endpoints - while (num_endpoints > 0 && p_desc < desc_end) { + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)(p_desc + sizeof(tusb_desc_interface_t)); + TU_VERIFY((uint8_t const *)(desc_ep + num_endpoints) <= p_end, 0); - // open endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + // open all endpoints + for (int i = 0; i < num_endpoints; i++) + TU_ASSERT(usbd_edpt_open(rhport, desc_ep + i)); - p_desc = tu_desc_next(p_desc); - num_endpoints--; + p_desc = (uint8_t const *)(desc_ep + num_endpoints); } - uint16_t processed_bytes = p_desc - (uint8_t const *) desc_intf; + uint16_t processed_bytes = p_desc - (uint8_t const *)desc_intf; cust_vendor_intf_open_cb(desc_intf->bInterfaceNumber); diff --git a/test-devices/composite-stm32/src/vendor_custom.h b/test-devices/composite-stm32/src/vendor_custom.h index 4d976a1a..da0618c0 100644 --- a/test-devices/composite-stm32/src/vendor_custom.h +++ b/test-devices/composite-stm32/src/vendor_custom.h @@ -32,6 +32,10 @@ /* Endpoint */\ 7, TUSB_DESC_ENDPOINT, _epaddr, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_packetsize), _interval +// Interface association descriptor: first interface index, number of interfaces, string index of description +#define CUSTOM_VENDOR_INTERFACE_ASSOCIATION(_firstintf, _numintf, _strIndex) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _firstintf, _numintf, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _strIndex // --- Application API diff --git a/test-devices/loopback-stm32/.vscode/settings.json b/test-devices/loopback-stm32/.vscode/settings.json index a92d1337..11ada5d0 100644 --- a/test-devices/loopback-stm32/.vscode/settings.json +++ b/test-devices/loopback-stm32/.vscode/settings.json @@ -3,6 +3,10 @@ "usbd.h": "c", "usbd_pvt.h": "c", "dwc2_stm32.h": "c", - "stm32f7xx.h": "c" + "stm32f7xx.h": "c", + "stm32f4xx.h": "c", + "stm32f401xc.h": "c", + "stm32f401xe.h": "c", + "tusb_option.h": "c" } } \ No newline at end of file diff --git a/test-devices/loopback-stm32/README.md b/test-devices/loopback-stm32/README.md index a30ffa10..45332099 100644 --- a/test-devices/loopback-stm32/README.md +++ b/test-devices/loopback-stm32/README.md @@ -7,21 +7,22 @@ For testing the *Java Does USB* library, a dedicated USB test device is needed. - BlackPill with STM32F401CC microcontroller - BlackPill with STM32F411CE microcontroller - BluePill with STM32F103C8 microcontroller +- STM32F723 Discovery board -To upload the firmware, the STM32F4x microcontroller have a built-in USB bootloader. The STM32F1x microcontrollers need an ST-Link debug adapter (or a USB-to-serial converter). +To upload the firmware, the STM32F4x microcontroller have a built-in USB bootloader. The STM32F1x microcontrollers need an ST-Link debug adapter (or a USB-to-serial converter). The STM32F723 Discovery board has a built-in ST-Link programmer. ## Test features ### Endpoints -| Endpoint | Transfer Type | Direction | Packet Size | Function | -| - | - | - | - | - | -| 0x00 | Control | Bidirectional | | See *Control requests* below | -| 0x01 | Bulk | Host to device | 64 bytes | Loopback: all data received on this endpoint are then transmitted on endpoint 0x82. | -| 0x82 | Bulk | Device to host | 64 bytes | Loopback: Transmits the data received on endpoint 0x01. | -| 0x03 | Interrupt | Host to device | 16 bytes | Echo: All packets received on this endpoint are transmitted twice on endpoint 0x83. | -| 0x83 | Interrupt | Device to host | 16 bytes | Echo: Transmits all packets received on endpoint 0x03 twice. | +| Endpoint | Transfer Type | Direction | Packet Size | Interface | Function | +| - | - | - | - | - | - | +| 0x00 | Control | Bidirectional | | 0 | See *Control requests* below | +| 0x01 | Bulk | Host to device | 64 bytes | 0 | Loopback: all data received on this endpoint are then transmitted on endpoint 0x82. | +| 0x82 | Bulk | Device to host | 64 bytes | 0 | Loopback: Transmits the data received on endpoint 0x01. | +| 0x03 | Interrupt | Host to device | 16 bytes | 0 | Echo: All packets received on this endpoint are transmitted twice on endpoint 0x83. | +| 0x83 | Interrupt | Device to host | 16 bytes | 0 | Echo: Transmits all packets received on endpoint 0x03 twice. | The bulk endpoints 0x01 and 0x82 use an internal buffer of about 500 bytes. Data up to this amount can be sent and received sequentially. If more data is sent without receiving at the same time, flow control kicks in and endpoint 0x01 will stop receiving data until there is room in the buffer. @@ -45,6 +46,18 @@ Two alternate interfaces are implemented: - Alternate 1: only the control endpoint and the bulk endpoints (0x01 and 0x82) are available +### Suspend / resume + +The device can be put into suspend mode by the host. It will go into a low-power mode. This is indicated by the user LED turning off. The power LED will stay on. The device can be woken up by the host. + +To put the device into suspended mode, put the host computer to sleep or supended mode. To wake it up, wake up the host computer. + +NOTE: *Due to a limitation of TinyUSB, the device will only go into suspended mode if the host has set a USB configuration. Usually it means that an application has communicated with the device after it was plugged in. The LED blinks as long as no USB configuration has been set.* + +NOTE: *Suspend/resume has not been implemented for the STM32F723 Discovery board.* + + + ## Building the firmware This project requires [PlatformIO](https://platformio.org/). The easiest way to get up and running is to use Visual Studio Code and then install the [PlatformIO IDE extension](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide). @@ -69,6 +82,7 @@ The directory `bin` contains a pre-built firmware: - `blackpill-f401cc.bin`: Firmware for BlackPill with STM32F401CC microcontroller - `blackpill-f411ce.bin`: Firmware for BlackPill with STM32F411CE microcontroller - `bluepill-f103c8.bin`: Firmware for BluePill with STM32F103C8 microcontroller +- `disco_f723ie.bin`: Firmware for STM32F723 Discovery board ### Upload using built-in bootloader @@ -111,4 +125,4 @@ If you built the firmware yourself, you will find the firmware file in `.pio/bui This code uses the CMSIS 5 library (mainly for startup code and register definitions) and TinyUSB for USB. For easier use with PlatformIO, a copy of TinyUSB is integrated into the project. The used TinyUSB code in `lib/tinyusb` is an unmodified subset of the library. -Since the official TinyUSB vendor class is rather limited, an alternative implementation is provided (see [vendor_custom.h](include/vendor_custom.h) and [vendor_custom.c](src/vendor_custom.c)). \ No newline at end of file +Since the official TinyUSB vendor class is rather limited, an alternative implementation is provided (see [vendor_custom.h](src/vendor_custom.h) and [vendor_custom.c](src/vendor_custom.c)). \ No newline at end of file diff --git a/test-devices/loopback-stm32/bin/blackpill-f401cc.bin b/test-devices/loopback-stm32/bin/blackpill-f401cc.bin index 852fc6dd..f4ab388c 100755 Binary files a/test-devices/loopback-stm32/bin/blackpill-f401cc.bin and b/test-devices/loopback-stm32/bin/blackpill-f401cc.bin differ diff --git a/test-devices/loopback-stm32/bin/blackpill-f411ce.bin b/test-devices/loopback-stm32/bin/blackpill-f411ce.bin index d0392747..da3a8766 100755 Binary files a/test-devices/loopback-stm32/bin/blackpill-f411ce.bin and b/test-devices/loopback-stm32/bin/blackpill-f411ce.bin differ diff --git a/test-devices/loopback-stm32/bin/bluepill-f103c8.bin b/test-devices/loopback-stm32/bin/bluepill-f103c8.bin index c39ace15..9f0eaf0b 100755 Binary files a/test-devices/loopback-stm32/bin/bluepill-f103c8.bin and b/test-devices/loopback-stm32/bin/bluepill-f103c8.bin differ diff --git a/test-devices/loopback-stm32/bin/disco_f723ie.bin b/test-devices/loopback-stm32/bin/disco_f723ie.bin index 1567e9e6..b8c2ab31 100755 Binary files a/test-devices/loopback-stm32/bin/disco_f723ie.bin and b/test-devices/loopback-stm32/bin/disco_f723ie.bin differ diff --git a/test-devices/loopback-stm32/copy_tinyusb.sh b/test-devices/loopback-stm32/copy_tinyusb.sh new file mode 100755 index 00000000..3021ce18 --- /dev/null +++ b/test-devices/loopback-stm32/copy_tinyusb.sh @@ -0,0 +1,15 @@ +#!/bin/sh +TINYUSB_DIR=../../../tinyusb +rm -rf lib/tinyusb/* +mkdir lib/tinyusb/osal +mkdir lib/tinyusb/portable +mkdir lib/tinyusb/portable/synopsys +mkdir lib/tinyusb/portable/st +cp -R $TINYUSB_DIR/src/common lib/tinyusb +cp -R $TINYUSB_DIR/src/device lib/tinyusb +cp $TINYUSB_DIR/src/osal/osal.h lib/tinyusb/osal +cp $TINYUSB_DIR/src/osal/osal_none.h lib/tinyusb/osal +cp -R $TINYUSB_DIR/src/portable/synopsys/dwc2 lib/tinyusb/portable/synopsys +cp -R $TINYUSB_DIR/src/portable/st/stm32_fsdev lib/tinyusb/portable/st +cp $TINYUSB_DIR/src/*.c lib/tinyusb +cp $TINYUSB_DIR/src/*.h lib/tinyusb diff --git a/test-devices/loopback-stm32/lib/tinyusb/tusb_config.h b/test-devices/loopback-stm32/lib/config/tusb_config.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/tusb_config.h rename to test-devices/loopback-stm32/lib/config/tusb_config.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio.h b/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio.h deleted file mode 100644 index 70d43128..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio.h +++ /dev/null @@ -1,935 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Audio Audio - * Currently only MIDI subclass is supported - * @{ */ - -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// Audio Device Class Codes - -/// A.2 - Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// A.3 - Audio Function Protocol Codes -typedef enum -{ - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_function_protocol_code_t; - -/// A.5 - Audio Interface Subclass Codes -typedef enum -{ - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming -} audio_subclass_type_t; - -/// A.6 - Audio Interface Protocol Codes -typedef enum -{ - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_interface_protocol_code_t; - -/// A.7 - Audio Function Category Codes -typedef enum -{ - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, -} audio_function_code_t; - -/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_ac_interface_subtype_t; - -/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, -} audio_cs_as_interface_subtype_t; - -/// A.11 - Effect Unit Effect Types -typedef enum -{ - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, -} audio_effect_unit_effect_type_t; - -/// A.12 - Processing Unit Process Types -typedef enum -{ - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, -} audio_processing_unit_process_type_t; - -/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - -/// A.14 - Audio Class-Specific Request Codes -typedef enum -{ - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, -} audio_cs_req_t; - -/// A.17 - Control Selector Codes - -/// A.17.1 - Clock Source Control Selectors -typedef enum -{ - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, -} audio_clock_src_control_selector_t; - -/// A.17.2 - Clock Selector Control Selectors -typedef enum -{ - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, -} audio_clock_sel_control_selector_t; - -/// A.17.3 - Clock Multiplier Control Selectors -typedef enum -{ - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, -} audio_clock_mul_control_selector_t; - -/// A.17.4 - Terminal Control Selectors -typedef enum -{ - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, -} audio_terminal_control_selector_t; - -/// A.17.5 - Mixer Control Selectors -typedef enum -{ - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, -} audio_mixer_control_selector_t; - -/// A.17.6 - Selector Control Selectors -typedef enum -{ - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, -} audio_sel_control_selector_t; - -/// A.17.7 - Feature Unit Control Selectors -typedef enum -{ - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, -} audio_feature_unit_control_selector_t; - -/// A.17.8 Effect Unit Control Selectors - -/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors -typedef enum -{ - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, -} audio_parametric_equalizer_control_selector_t; - -/// A.17.8.2 Reverberation Effect Unit Control Selectors -typedef enum -{ - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, -} audio_reverberation_effect_control_selector_t; - -/// A.17.8.3 Modulation Delay Effect Unit Control Selectors -typedef enum -{ - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, -} audio_modulation_delay_control_selector_t; - -/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors -typedef enum -{ - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, -} audio_dynamic_range_compression_control_selector_t; - -/// A.17.9 Processing Unit Control Selectors - -/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors -typedef enum -{ - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, -} audio_up_down_mix_control_selector_t; - -/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors -typedef enum -{ - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, -} audio_dolby_prologic_control_selector_t; - -/// A.17.9.3 Stereo Extender Processing Unit Control Selectors -typedef enum -{ - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, -} audio_stereo_extender_control_selector_t; - -/// A.17.10 Extension Unit Control Selectors -typedef enum -{ - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, -} audio_extension_unit_control_selector_t; - -/// A.17.11 AudioStreaming Interface Control Selectors -typedef enum -{ - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, -} audio_audiostreaming_interface_control_selector_t; - -/// A.17.12 Encoder Control Selectors -typedef enum -{ - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, -} audio_encoder_control_selector_t; - -/// A.17.13 Decoder Control Selectors - -/// A.17.13.1 MPEG Decoder Control Selectors -typedef enum -{ - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, -} audio_MPEG_decoder_control_selector_t; - -/// A.17.13.2 AC-3 Decoder Control Selectors -typedef enum -{ - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, -} audio_AC3_decoder_control_selector_t; - -/// A.17.13.3 WMA Decoder Control Selectors -typedef enum -{ - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, -} audio_WMA_decoder_control_selector_t; - -/// A.17.13.4 DTS Decoder Control Selectors -typedef enum -{ - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, -} audio_DTS_decoder_control_selector_t; - -/// A.17.14 Endpoint Control Selectors -typedef enum -{ - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, -} audio_EP_control_selector_t; - -/// Terminal Types - -/// 2.1 - Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// 2.2 - Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - -/// 2.3 - Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - -/// Rest is yet to be implemented - -/// Additional Audio Device Class Codes - Source: Audio Data Formats - -/// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, -} audio_data_format_type_I_t; - -/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - -/// Audio Class-Control Values UAC2 -typedef enum -{ - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access -} audio_control_t; - -/// Audio Class-Specific AC Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, -} audio_cs_ac_interface_control_pos_t; - -/// Audio Class-Specific AS Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, -} audio_cs_as_interface_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, -} audio_cs_as_iso_data_ep_attribute_t; - -/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, -} audio_cs_as_iso_data_ep_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, -} audio_cs_as_iso_data_ep_lock_delay_unit_t; - -/// Audio Class-Clock Source Attributes UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, -} audio_clock_source_attribute_t; - -/// Audio Class-Clock Source Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, -} audio_clock_source_control_pos_t; - -/// Audio Class-Clock Selector Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, -} audio_clock_selector_control_pos_t; - -/// Audio Class-Clock Multiplier Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, -} audio_clock_multiplier_control_pos_t; - -/// Audio Class-Input Terminal Controls UAC2 -typedef enum -{ - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, -} audio_terminal_input_control_pos_t; - -/// Audio Class-Output Terminal Controls UAC2 -typedef enum -{ - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, -} audio_terminal_output_control_pos_t; - -/// Audio Class-Feature Unit Controls UAC2 -typedef enum -{ - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, -} audio_feature_unit_control_pos_t; - -/// Audio Class-Audio Channel Configuration UAC2 -typedef enum -{ - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, -} audio_channel_config_t; - -/// AUDIO Channel Cluster Descriptor (4.1) -typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. -} audio_desc_channel_cluster_t; - -/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. -} audio_desc_cs_ac_interface_t; - -/// AUDIO Clock Source Descriptor (4.7.2.1) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. -} audio_desc_clock_source_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. -} audio_desc_clock_selector_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins -#define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ -} - -/// AUDIO Clock Multiplier Descriptor (4.7.2.3) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. -} audio_desc_clock_multiplier_t; - -/// AUDIO Input Terminal Descriptor(4.7.2.4) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first logical channel. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. -} audio_desc_input_terminal_t; - -/// AUDIO Output Terminal Descriptor(4.7.2.5) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. -} audio_desc_output_terminal_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. -} audio_desc_feature_unit_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ -} - -/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. -} audio_desc_cs_as_interface_t; - -/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. -} audio_desc_type_I_format_t; - -/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. -} audio_desc_cs_as_iso_data_ep_t; - -// 5.2.2 Control Request Layout -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - -//// 5.2.3 Control Request Parameter Block Layout - -// 5.2.3.1 1-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_1_t; - -// 5.2.3.2 2-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_2_t; - -// 5.2.3.3 4-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_4_t; - -// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like -// 5.2.3.1 1-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_1_t; - -// 5.2.3.2 2-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_2_t; - -// 5.2.3.3 4-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_4_t; - -// 5.2.3.1 1-byte Control RANGE Parameter Block -#define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ -} - -/// 5.2.3.2 2-byte Control RANGE Parameter Block -#define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -// 5.2.3.3 4-byte Control RANGE Parameter Block -#define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.c deleted file mode 100644 index f487fe60..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.c +++ /dev/null @@ -1,2567 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! - * It supports multiple TX and RX channels. - * - * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. - * - * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host - * - * 1. Input data -> SW-FIFO -> MCU USB - * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) - * - * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB - * - * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. - * - * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB - * - * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. - * - * The same holds in the RX case. - * - * */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_AUDIO) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "audio_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Use ring buffer if it's available, some MCUs need extra RAM requirements -#ifndef TUD_AUDIO_PREFER_RING_BUFFER - #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT - #define TUD_AUDIO_PREFER_RING_BUFFER 0 - #else - #define TUD_AUDIO_PREFER_RING_BUFFER 1 - #endif -#endif - -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer -// is available or driver is would need to be changed dramatically - -// Only STM32 and dcd_transdimension use non-linear buffer for now -// dwc2 except esp32sx (since it may use dcd_esp32sx) -#if (defined(TUP_USBIP_DWC2) && !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)) || \ - defined(TUP_USBIP_FSDEV) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N || \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT || \ - CFG_TUSB_MCU == OPT_MCU_MSP432E4 - #if TUD_AUDIO_PREFER_RING_BUFFER - #define USE_LINEAR_BUFFER 0 - #else - #define USE_LINEAR_BUFFER 1 - #endif -#else - #define USE_LINEAR_BUFFER 1 -#endif - -// Temporarily put the check here for stm32_fsdev -#ifdef TUP_USBIP_FSDEV - #define USE_ISO_EP_ALLOCATION 1 -#else - #define USE_ISO_EP_ALLOCATION 0 -#endif - -// Declaration of buffers - -// Check for maximum supported numbers -#if CFG_TUD_AUDIO > 3 -#error Maximum number of audio functions restricted to three! -#endif - -// EP IN software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -// Linear buffer TX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// EP OUT software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -// Linear buffer RX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// Control buffers -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; - -#if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif - -#if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif - -// Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; -#endif - -// Software encoding/decoding support FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO - #endif - #endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO - #endif - #endif -#endif - -typedef struct -{ - uint8_t rhport; - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in; // TX audio data EP. - uint16_t ep_in_sz; // Current size of TX EP - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint16_t ep_out_sz; // Current size of RX EP - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. -#endif - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. -#endif - - /*------------- From this point, data is not cleared by bus reset -------------*/ - - uint16_t desc_length; // Length of audio function descriptor - - // Buffer for control requests - uint8_t * ctrl_buf; - uint8_t ctrl_buf_sz; - - // Current active alternate settings - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - - // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t ep_out_ff; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - struct { - CFG_TUSB_MEM_ALIGN uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). - uint32_t min_value; // min value according to UAC2 FMT-2.0 section 2.3.1.1. - uint32_t max_value; // max value according to UAC2 FMT-2.0 section 2.3.1.1. - - uint8_t frame_shift; // bInterval-1 in unit of frame (FS), micro-frame (HS) - uint8_t compute_method; - - union { - uint8_t power_of_2; // pre-computed power of 2 shift - float float_const; // pre-computed float constant - - struct { - uint32_t sample_freq; - uint32_t mclk_freq; - }fixed; - -#if 0 // implement later - struct { - uint32_t nominal_value; - uint32_t threshold_bytes; - }fifo_count; -#endif - }compute; - - } feedback; -#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t ep_in_ff; -#endif - - // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; -#endif - - // Decoding parameters - parameters are set when alternate AS interface is set by host - // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - audio_format_type_t format_type_rx; - uint8_t n_channels_rx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sampe_rx; - uint8_t n_channels_per_ff_rx; - uint8_t n_ff_used_rx; -#endif -#endif - - // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - audio_format_type_t format_type_tx; - uint8_t n_channels_tx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio_data_format_type_I_t format_type_I_tx; - uint8_t n_bytes_per_sampe_tx; - uint8_t n_channels_per_ff_tx; - uint8_t n_ff_used_tx; -#endif -#endif - - // Support FIFOs for software encoding and decoding -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t * rx_supp_ff; - uint8_t n_rx_supp_ff; - uint16_t rx_supp_ff_sz_max; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t * tx_supp_ff; - uint8_t n_tx_supp_ff; - uint16_t tx_supp_ff_sz_max; -#endif - - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - uint8_t * lin_buf_out; -#define USE_LINEAR_BUFFER_RX 1 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - uint8_t * lin_buf_in; -#define USE_LINEAR_BUFFER_TX 1 -#endif - -} audiod_function_t; - -#ifndef USE_LINEAR_BUFFER_TX -#define USE_LINEAR_BUFFER_TX 0 -#endif - -#ifndef USE_LINEAR_BUFFER_RX -#define USE_LINEAR_BUFFER_RX 0 -#endif - -#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); -#endif - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); - -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); -static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); - -static inline uint8_t tu_desc_subtype(void const* desc) -{ - return ((uint8_t const*) desc)[2]; -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); -#endif - -bool tud_audio_n_mounted(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in == 0) return false; -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) return false; -#endif - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -uint16_t tud_audio_n_available(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); -} - -uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); -} - -bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -// Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); -} - -tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; - return NULL; -} -#endif - -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - uint8_t idxItf = 0; - uint8_t const *dummy2; - uint8_t idx_audio_fct = 0; - - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) - { - TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - - switch (audio->format_type_rx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_rx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - - // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - -#else - -#if USE_LINEAR_BUFFER_RX - // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); - - // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) - { - TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT - -// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Decoding according to 2.3.1.5 Audio Streams - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) -{ - - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint8_t *)dst++ = *src; - src += n_ff_used; - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - dst += 4; - src += 4 * n_ff_used; - } - break; - } - - return src; -} - -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - (void) rhport; - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; - uint8_t cnt_ff; - - // Decode - uint8_t * src; - uint8_t * dst_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); - if (info.len_wrap != 0) - { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); - } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it - // TU_VERIFY(cnt != n_bytes); - - return true; -} -#endif //CFG_TUD_AUDIO_ENABLE_DECODING - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] func_id: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); -} - -bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[func_id]; - - uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); - - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - - n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); - n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; - - return n_bytes_copied; -} - -bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); -} - -tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; - return NULL; -} - -#endif - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); - - TU_VERIFY(tu_memcpy_s(_audiod_fct[func_id].ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE, buffer, len)==0); - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); - - return true; -} - -#endif - - -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. - -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) -{ - uint8_t idxItf; - uint8_t const *dummy2; - - uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); - - // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications - if (audio->alt_setting[idxItf] == 0) return false; - - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx; - - // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - switch (audio->format_type_tx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - - n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); - break; - - default: - // YOUR ENCODING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - -#else - // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - -#if USE_LINEAR_BUFFER_TX - tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); -#else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -// Take samples from the support buffer and encode them into the IN EP software FIFO -// Returns number of bytes written into linear buffer - -/* 2.3.1.7.1 PCM Format -The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio -data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It -is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused -bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the -range [-1, +1) - */ - -/* - * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples - * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and - * does not change the number of bytes per sample. - * */ - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) -{ - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while(src < src_end) - { - *dst = *src++; - dst += n_ff_used; - } - break; - - case 2: - while(src < src_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; - } - break; - - case 3: - while(src < src_end) - { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - src += 4; - dst += 4 * n_ff_used; - } - break; - } - - return dst; -} - -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) -{ - // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap - // This is ensured within set_interface, where the FIFOs are reconfigured according to this size - - // We encode directly into IN EP's linear buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; - uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes - uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); - uint8_t cnt_ff; - - for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) - { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nBytesPerFFToSend) - { - nBytesPerFFToSend = count; - } - } - - // Check if there is enough - if (nBytesPerFFToSend == 0) return 0; - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); - - // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; - - // Encode - uint8_t * dst; - uint8_t * src_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); - - // Limit up to desired length - info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) - { - src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); - } - - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - return nBytesPerFFToSend * n_ff_used; -} -#endif //CFG_TUD_AUDIO_ENABLE_ENCODING - -// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) -{ - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->feedback.value, 4); -} -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void audiod_init(void) -{ - tu_memclr(_audiod_fct, sizeof(_audiod_fct)); - - for(uint8_t i=0; ictrl_buf = ctrl_buf_1; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; - break; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 - case 1: - audio->ctrl_buf = ctrl_buf_2; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 - case 2: - audio->ctrl_buf = ctrl_buf_3; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; - break; -#endif - } - - // Initialize active alternate interface buffers - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 - case 0: - audio->alt_setting = alt_setting_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 - case 1: - audio->alt_setting = alt_setting_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - case 2: - audio->alt_setting = alt_setting_3; - break; -#endif - } - - // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_TX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - case 0: - audio->lin_buf_in = lin_buf_in_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - case 1: - audio->lin_buf_in = lin_buf_in_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - case 2: - audio->lin_buf_in = lin_buf_in_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_RX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - case 0: - audio->lin_buf_out = lin_buf_out_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - case 1: - audio->lin_buf_out = lin_buf_out_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - case 2: - audio->lin_buf_out = lin_buf_out_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->tx_supp_ff = tx_supp_ff_1; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->tx_supp_ff = tx_supp_ff_2; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->tx_supp_ff = tx_supp_ff_3; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - - // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->rx_supp_ff = rx_supp_ff_1; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->rx_supp_ff = rx_supp_ff_2; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->rx_supp_ff = rx_supp_ff_3; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - } -} - -void audiod_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; iep_in_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - } -} - -uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_fct[i].p_desc) - { - _audiod_fct[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - _audiod_fct[i].rhport = rhport; - - // Setup descriptor lengths - switch (i) - { - case 0: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; - break; -#if CFG_TUD_AUDIO > 1 - case 1: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; - break; -#endif -#if CFG_TUD_AUDIO > 2 - case 2: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; - break; -#endif - } - -#if USE_ISO_EP_ALLOCATION - #if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in = 0; - uint16_t ep_in_size = 0; - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out = 0; - uint16_t ep_out_size = 0; - #endif - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb = 0; - #endif - - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Explicit feedback EP - if (desc_ep->bmAttributes.usage == 1) - { - ep_fb = desc_ep->bEndpointAddress; - } - #endif - // Data EP - if (desc_ep->bmAttributes.usage == 0) - { - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - #if CFG_TUD_AUDIO_ENABLE_EP_IN - ep_in = desc_ep->bEndpointAddress; - ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); - #endif - } else - { - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - ep_out = desc_ep->bEndpointAddress; - ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); - #endif - } - } - - } - } - p_desc = tu_desc_next(p_desc); - } - - #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (ep_in) - { - usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (ep_out) - { - usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (ep_fb) - { - usbd_edpt_iso_alloc(rhport, ep_fb, 4); - } - #endif - -#endif // USE_ISO_EP_ALLOCATION - - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; -} - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - uint8_t const itf = tu_u16_low(p_request->wIndex); - - // Find index of audio streaming interface - uint8_t func_id, idxItf; - uint8_t const *dummy; - - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); - - return true; -} - -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Here we need to do the following: - - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - - // 3. Open new EP - - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); - - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - - // Find index of audio streaming interface and index of interface - uint8_t func_id, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - - audiod_function_t* audio = &_audiod_fct[func_id]; - - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in_as_intf_num == itf) - { - audio->ep_in_as_intf_num = 0; - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_in); - #endif - - // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_clear(&audio->ep_in_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } - #endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_in = 0; // Necessary? - - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out_as_intf_num == itf) - { - audio->ep_out_as_intf_num = 0; - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_out); - #endif - - // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } - #endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_out = 0; // Necessary? - - // Close corresponding feedback EP - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - #if !USE_ISO_EP_ALLOCATION - usbd_edpt_close(rhport, audio->ep_fb); - #endif - audio->ep_fb = 0; - tu_memclr(&audio->feedback, sizeof(audio->feedback)); - #endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - // Save current alternative interface setting - audio->alt_setting[idxItf] = alt; - - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) - { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING - uint8_t const * p_desc_parse_for_params = p_desc; -#endif - // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary - uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; - while (foundEPs < nEps && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; -#if USE_ISO_EP_ALLOCATION - TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep)); -#else - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); -#endif - uint8_t const ep_addr = desc_ep->bEndpointAddress; - - //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! - usbd_edpt_clear_stall(rhport, ep_addr); - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - audio->ep_in = ep_addr; - audio->ep_in_as_intf_num = itf; - audio->ep_in_sz = tu_edpt_packet_size(desc_ep); - - // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters - #if CFG_TUD_AUDIO_ENABLE_ENCODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx); - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; - TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); - #endif - #endif - - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - audio->ep_out = ep_addr; - audio->ep_out_as_intf_num = itf; - audio->ep_out_sz = tu_edpt_packet_size(desc_ep); - - #if CFG_TUD_AUDIO_ENABLE_DECODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; - TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); - #endif - #endif - - // Prepare for incoming data - #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - #else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); - #endif - } - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback - { - audio->ep_fb = ep_addr; - audio->feedback.frame_shift = desc_ep->bInterval -1; - - // Enable SOF interrupt if callback is implemented - if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, true); - } - #endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } - - TU_VERIFY(foundEPs == nEps); - - // Invoke one callback for a final set interface - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Prepare feedback computation if callback is available - if (tud_audio_feedback_params_cb) - { - audio_feedback_params_t fb_param; - - tud_audio_feedback_params_cb(func_id, alt, &fb_param); - audio->feedback.compute_method = fb_param.method; - - // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) - uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; - audio->feedback.min_value = (fb_param.sample_freq/frame_div - 1) << 16; - audio->feedback.max_value = (fb_param.sample_freq/frame_div + 1) << 16; - - switch(fb_param.method) - { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); - break; - - #if 0 // implement later - case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: - { - uint64_t fb64 = ((uint64_t) fb_param.sample_freq) << 16; - audio->feedback.compute.fifo_count.nominal_value = (uint32_t) (fb64 / frame_div); - audio->feedback.compute.fifo_count.threshold_bytes = fb_param.fifo_count.threshold_bytes; - - tud_audio_fb_set(audio->feedback.compute.fifo_count.nominal_value); - } - break; - #endif - - // nothing to do - default: break; - } - } -#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - - // We are done - abort loop - break; - } - - // Moving forward - p_desc = tu_desc_next(p_desc); - } - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Disable SOF interrupt if no driver has any enabled feedback EP - bool disable = true; - for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].ep_fb != 0) - { - disable = false; - break; - } - } - if (disable) usbd_sof_enable(rhport, false); -#endif - - tud_control_status(rhport, p_request); - - return true; -} - -// Invoked when class request DATA stage is finished. -// return false to stall control EP (e.g Host send non-sense DATA) -static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) - { - uint8_t func_id; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - break; - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } - } - return true; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); - - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t func_id; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); - return true; - } - - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; -} - -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - return audiod_control_request(rhport, request); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - return audiod_control_complete(rhport, request); - } - - return true; -} - -bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) xferred_bytes; - - // Search for interface belonging to given end point address and proceed as required - for (uint8_t func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) - { - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - - // Data transmission of control interrupt finished - if (audio->ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // I assume here, that things above are handled by PHY - // All transmission is done - what remains to do is to inform job was completed - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); - } - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - - // Data transmission of audio packet finished - if (audio->ep_in == ep_addr && audio->alt_setting != 0) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, audio)); - - // Transmission of ZLP is done by audiod_tx_done_cb() - return true; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - // New audio packet received - if (audio->ep_out == ep_addr) - { - TU_VERIFY(audiod_rx_done_cb(rhport, audio, (uint16_t) xferred_bytes)); - return true; - } - - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (audio->ep_fb == ep_addr) - { - if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id); - - // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, audio->ep_fb)) - { - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, audio); - } - } -#endif -#endif - } - - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) -{ - // Check if frame interval is within sane limits - // The interval value n_frames was taken from the descriptors within audiod_set_interface() - - // n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 * f_s / f_m) for high speed - // this lower limit ensures the measures feedback value has sufficient precision - uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13; - uint32_t const n_frame = (1UL << audio->feedback.frame_shift); - - if ( (((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame ) - { - TU_LOG1(" UAC2 feedback interval too small\r\n"); TU_BREAKPOINT(); return false; - } - - // Check if parameters really allow for a power of two division - if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq)) - { - audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; - audio->feedback.compute.power_of_2 = 16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq); - } - else if ( audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) - { - audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - audio->feedback.frame_shift)); - } - else - { - audio->feedback.compute.fixed.sample_freq = sample_freq; - audio->feedback.compute.fixed.mclk_freq = mclk_freq; - } - - return true; -} - -uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) -{ - audiod_function_t* audio = &_audiod_fct[func_id]; - uint32_t feedback; - - switch (audio->feedback.compute_method) - { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - feedback = (cycles << audio->feedback.compute.power_of_2); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - feedback = (uint32_t) ((float) cycles * audio->feedback.compute.float_const); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: - { - uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - audio->feedback.frame_shift); - feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); - } - break; - - default: return 0; - } - - // For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers - // The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. - // This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot - // (audio slot = channel count samples). - if ( feedback > audio->feedback.max_value ) feedback = audio->feedback.max_value; - if ( feedback < audio->feedback.min_value ) feedback = audio->feedback.min_value; - - tud_audio_n_fb_set(func_id, feedback); - - return feedback; -} -#endif - -TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) -{ - (void) rhport; - (void) frame_count; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec - // Boiled down, the feedback value Ff = n_samples / (micro)frame. - // Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) - // The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) - // feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - - // Iterate over audio functions and set feedback value - for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) - { - audiod_function_t* audio = &_audiod_fct[i]; - - if (audio->ep_fb != 0) - { - // HS shift need to be adjusted since SOF event is generated for frame only - uint8_t const hs_adjust = (TUSB_SPEED_HIGH == tud_speed_get()) ? 3 : 0; - uint32_t const interval = 1UL << (audio->feedback.frame_shift - hs_adjust); - if ( 0 == (frame_count & (interval-1)) ) - { - if(tud_audio_feedback_interval_isr) tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); - } - } - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -} - -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) -{ - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - - // Get corresponding driver index - uint8_t func_id; - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // Crop length - if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; - - // Copy into buffer - TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len)); - - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); -} - -// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - if (audio->p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(audio->p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) - { - if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; - } - // Increase index, bytes read, and pointer - tmp++; - } - p_desc = tu_desc_next(p_desc); - } - } - return false; -} - -// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) - { - *func_id = i; - return true; - } - } - - return false; -} - -// Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -// p_desc points to the AS interface of alternate setting zero -// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter -// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) -{ -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) return; // Abort, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) return; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) return; -#endif - - p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor - - while (p_desc < p_desc_end) - { - // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; - - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); -#endif - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; -#endif - } -#endif - } - - // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - } -#endif - - // Other format types are not supported yet - - p_desc = tu_desc_next(p_desc); - } -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].feedback.value; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].feedback.value = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - -// No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) -{ - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) - { - if (&_audiod_fct[cnt] == audio) return cnt; - } - return 0; -} - -#endif //CFG_TUD_ENABLED && CFG_TUD_AUDIO diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.h deleted file mode 100644 index 7c88b99f..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/audio/audio_device.h +++ /dev/null @@ -1,699 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_AUDIO_DEVICE_H_ -#define _TUSB_AUDIO_DEVICE_H_ - -#include "audio.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// All sizes are in bytes! - -#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif - -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces -#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif - -// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif - -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN -#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT -#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX -#endif - -// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Software EP FIFO buffer sizes - must be >= max EP SIZEs! -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 -#endif - -// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 -#endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -// Use software encoding/decoding - -// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved -// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. -// -// Currently, only PCM type I encoding/decoding is supported! -// -// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. - -// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the -// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using -// - tud_audio_n_write() or -// - tud_audio_n_read(). -// To write/read to/from the support FIFOs use -// - tud_audio_n_write_support_ff() or -// - tud_audio_n_read_support_ff(). -// -// The encoding/decoding format type done is defined below. -// -// The encoding/decoding starts when the private callback functions -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. -// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// if you want to get informed what happened. -// -// If you don't use the support FIFOs you may use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. -// -// If you need a different encoding which is not support so far implement it in the -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// functions. - -// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual coding parameters of active AS alternate interface is parsed from the descriptors - -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! -// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! - -// For PCM encoding/decoding - -#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_DECODING -#define CFG_TUD_AUDIO_ENABLE_DECODING 0 -#endif - -// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 -#endif - -// Type I Coding parameters not given within UAC2 descriptors -// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -// Remaining types not support so far - -// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface -#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 -#endif - -// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO -#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 -#endif - -//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); - -// Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup AUDIO_Serial Serial - * @{ - * \defgroup AUDIO_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_AUDIO > 1 -//--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t func_id); - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t func_id); -uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO -tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); -tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO -tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); -tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); -#endif - -//--------------------------------------------------------------------+ -// Application API (Interface0) -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted (void); - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void); -static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline bool tud_audio_clear_ep_in_ff (void); -static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); -static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); -#endif - -// INT CTR API - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); -#endif - -// Buffer control EP data and schedule a transmit -// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a -// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. -// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such -// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id); - - -// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced. - -// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). - -// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set(). - -// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. -// -// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. -// -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. - -// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value. - -// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec -// Boiled down, the feedback value Ff = n_samples / (micro)frame. -// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) -// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) -// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); - -// Update feedback value with passed cycles since last time this update function is called. -// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented -// This function will also call tud_audio_feedback_set() -// return feedback value in 16.16 for reference (0 for error) -uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles); - -enum { - AUDIO_FEEDBACK_METHOD_DISABLED, - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED, - AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT, - AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, - - // impelemnt later - // AUDIO_FEEDBACK_METHOD_FIFO_COUNT -}; - -typedef struct { - uint8_t method; - uint32_t sample_freq; // sample frequency in Hz - - union { - struct { - uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on - }frequency; - -#if 0 // implement later - struct { - uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready - }fifo_count; -#endif - }; -}audio_feedback_params_t; - -// Invoked when needed to set feedback parameters -TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); - -// Callback in ISR context, invoked periodically according to feedback endpoint bInterval. -// Could be used to compute and update feedback value, should be placed in RAM if possible -// frame_number : current SOF count -// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor -TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); -#endif - -// Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted(void) -{ - return tud_audio_n_mounted(0); -} - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -static inline uint16_t tud_audio_available(void) -{ - return tud_audio_n_available(0); -} - -static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read(0, buffer, bufsize); -} - -static inline bool tud_audio_clear_ep_out_ff(void) -{ - return tud_audio_n_clear_ep_out_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) -{ - return tud_audio_n_get_ep_out_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - -static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_rx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_available_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); -} - -static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_rx_support_ff(0, ff_idx); -} - -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_write(const void * data, uint16_t len) -{ - return tud_audio_n_write(0, data, len); -} - -static inline bool tud_audio_clear_ep_in_ff(void) -{ - return tud_audio_n_clear_ep_in_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) -{ - return tud_audio_n_get_ep_in_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_flush_tx_support_ff(void) -{ - return tud_audio_n_flush_tx_support_ff(0); -} - -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_tx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) -{ - return tud_audio_n_write_support_ff(0, ff_idx, data, len); -} - -static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_tx_support_ff(0, ff_idx); -} - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) -{ - return tud_audio_int_ctr_n_write(0, buffer, len); -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -static inline bool tud_audio_fb_set(uint32_t feedback) -{ - return tud_audio_n_fb_set(0, feedback); -} - -#endif - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); -void audiod_sof_isr (uint8_t rhport, uint32_t frame_count); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_AUDIO_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.c deleted file mode 100755 index f96bb355..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_BTH) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "bth_device.h" -#include - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_ev; - uint8_t ep_acl_in; - uint8_t ep_acl_out; - uint8_t ep_voice[2]; // Not used yet - uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; - -} btd_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; - -static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) -{ - uint8_t const rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, ep)); - - TU_ASSERT(usbd_edpt_xfer(rhport, ep, data, len)); - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -bool tud_bt_event_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_ev, event, event_len); -} - -bool tud_bt_acl_data_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void btd_init(void) -{ - tu_memclr(&_btd_itf, sizeof(_btd_itf)); -} - -void btd_reset(uint8_t rhport) -{ - (void)rhport; -} - -uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - tusb_desc_endpoint_t const *desc_ep; - uint16_t drv_len = 0; - // Size of single alternative of ISO interface - const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); - // Size of hci interface - const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); - // Ensure this is BT Primary Controller - TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - - TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); - - _btd_itf.itf_num = itf_desc->bInterfaceNumber; - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - _btd_itf.ep_ev = desc_ep->bEndpointAddress; - - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, - &_btd_itf.ep_acl_in), 0); - - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); - - // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); - - drv_len = hci_itf_size; - - // Ensure this is still BT Primary Controller - TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); - - uint8_t dir; - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - - for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { - // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); - if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || - TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || - TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { - // Not an Iso interface instance - break; - } - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ - (void)rhport; - - if ( stage == CONTROL_STAGE_SETUP ) - { - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) - { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) - { - // TODO: Set interface it would involve changing size of endpoint size - } - else - { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); - } - } - else return false; - - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); - } - - return true; -} - -bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - - // received new data from host - if (ep_addr == _btd_itf.ep_acl_out) - { - if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); - - // prepare for next data - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); - } - else if (ep_addr == _btd_itf.ep_ev) - { - if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); - } - else if (ep_addr == _btd_itf.ep_acl_in) - { - if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); - } - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.h deleted file mode 100755 index 921bd7a1..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/bth/bth_device.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ - -#include -#include - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#ifndef CFG_TUD_BTH_EVENT_EPSIZE -#define CFG_TUD_BTH_EVENT_EPSIZE 16 -#endif -#ifndef CFG_TUD_BTH_DATA_EPSIZE -#define CFG_TUD_BTH_DATA_EPSIZE 64 -#endif - -typedef struct TU_ATTR_PACKED -{ - uint16_t op_code; - uint8_t param_length; - uint8_t param[255]; -} bt_hci_cmd_t; - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when HCI command was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.1. -// Length of the command is from 3 bytes (2 bytes for OpCode, -// 1 byte for parameter total length) to 258. -TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); - -// Invoked when ACL data was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.2. -// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length) to endpoint size. -TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); - -// Called when event sent with tud_bt_event_send() was delivered to BT stack. -// Controller can release/reuse buffer with Event packet at this point. -TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); - -// Called when ACL data that was sent with tud_bt_acl_data_send() -// was delivered to BT stack. -// Controller can release/reuse buffer with ACL packet at this point. -TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); - -// Bluetooth controller calls this function when it wants to send even packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. -// Event has at least 2 bytes, first is Event code second contains parameter -// total length. Controller can release/reuse event memory after -// tud_bt_event_sent_cb() is called. -bool tud_bt_event_send(void *event, uint16_t event_len); - -// Bluetooth controller calls this to send ACL data packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 -// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length). Upper limit is not limited -// to endpoint size since buffer is allocate by controller -// and must not be reused till tud_bt_acl_data_sent_cb() is called. -bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc.h deleted file mode 100644 index 4658e43a..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** \defgroup ClassDriver_CDC_Common Common Definitions - * @{ */ - -//--------------------------------------------------------------------+ -// CDC Communication Interface Class -//--------------------------------------------------------------------+ - -/// Communication Interface Subclass Codes -typedef enum -{ - CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL = 0x02 , ///< Abstract Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL = 0x03 , ///< Telephone Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL = 0x04 , ///< Multi-Channel Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL = 0x05 , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL = 0x06 , ///< Ethernet Networking Control Model [USBECM1.2] - CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL = 0x07 , ///< ATM Networking Control Model [USBATM1.2] - CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL = 0x08 , ///< Wireless Handset Control Model [USBWMC1.1] - CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT = 0x09 , ///< Device Management [USBWMC1.1] - CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL = 0x0A , ///< Mobile Direct Line Model [USBWMC1.1] - CDC_COMM_SUBCLASS_OBEX = 0x0B , ///< OBEX [USBWMC1.1] - CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL = 0x0C , ///< Ethernet Emulation Model [USBEEM1.0] - CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL = 0x0D ///< Network Control Model [USBNCM1.0] -} cdc_comm_sublcass_type_t; - -/// Communication Interface Protocol Codes -typedef enum -{ - CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol - CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , ///< AT Commands: V.250 etc - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 = 0x02 , ///< AT Commands defined by PCCA-101 - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO = 0x03 , ///< AT Commands defined by PCCA-101 & Annex O - CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 = 0x04 , ///< AT Commands defined by GSM 07.07 - CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 = 0x05 , ///< AT Commands defined by 3GPP 27.007 - CDC_COMM_PROTOCOL_ATCOMMAND_CDMA = 0x06 , ///< AT Commands defined by TIA for CDMA - CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL = 0x07 ///< Ethernet Emulation Model -} cdc_comm_protocol_type_t; - -//------------- SubType Descriptor in COMM Functional Descriptor -------------// -/// Communication Interface SubType Descriptor -typedef enum -{ - CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. - CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor. - CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor. - CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor. - CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor - CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor - CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor - CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor - CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor - CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor - CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor - CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor - CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor - CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor - CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor - CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor - CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor - CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 , ///< OBEX Service Identifier Functional Descriptor - CDC_FUNC_DESC_NCM = 0x1A , ///< NCM Functional Descriptor -}cdc_func_desc_type_t; - -//--------------------------------------------------------------------+ -// CDC Data Interface Class -//--------------------------------------------------------------------+ - -// SUBCLASS code of Data Interface is not used and should/must be zero - -// Data Interface Protocol Codes -typedef enum{ - CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI - CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC - CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent - CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol - CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931 - CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol - CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures - CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control - CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN - CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands - CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack. - CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface -}cdc_data_protocol_type_t; - -//--------------------------------------------------------------------+ -// Management Element Request (Control Endpoint) -//--------------------------------------------------------------------+ - -/// Communication Interface Management Element Request Codes -typedef enum -{ - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. - CDC_REQUEST_SET_COMM_FEATURE = 0x02, - CDC_REQUEST_GET_COMM_FEATURE = 0x03, - CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04, - - CDC_REQUEST_SET_AUX_LINE_STATE = 0x10, - CDC_REQUEST_SET_HOOK_STATE = 0x11, - CDC_REQUEST_PULSE_SETUP = 0x12, - CDC_REQUEST_SEND_PULSE = 0x13, - CDC_REQUEST_SET_PULSE_TIME = 0x14, - CDC_REQUEST_RING_AUX_JACK = 0x15, - - CDC_REQUEST_SET_LINE_CODING = 0x20, - CDC_REQUEST_GET_LINE_CODING = 0x21, - CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22, - CDC_REQUEST_SEND_BREAK = 0x23, - - CDC_REQUEST_SET_RINGER_PARMS = 0x30, - CDC_REQUEST_GET_RINGER_PARMS = 0x31, - CDC_REQUEST_SET_OPERATION_PARMS = 0x32, - CDC_REQUEST_GET_OPERATION_PARMS = 0x33, - CDC_REQUEST_SET_LINE_PARMS = 0x34, - CDC_REQUEST_GET_LINE_PARMS = 0x35, - CDC_REQUEST_DIAL_DIGITS = 0x36, - CDC_REQUEST_SET_UNIT_PARAMETER = 0x37, - CDC_REQUEST_GET_UNIT_PARAMETER = 0x38, - CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39, - CDC_REQUEST_GET_PROFILE = 0x3A, - - CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43, - CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44, - - CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50, - CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51, - CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52, - CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, - - CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, -}cdc_management_request_t; - -enum -{ - CDC_CONTROL_LINE_STATE_DTR = 0x01, - CDC_CONTROL_LINE_STATE_RTS = 0x02, -}; - -enum -{ - CDC_LINE_CONDING_STOP_BITS_1 = 0, // 1 bit - CDC_LINE_CONDING_STOP_BITS_1_5 = 1, // 1.5 bits - CDC_LINE_CONDING_STOP_BITS_2 = 2, // 2 bits -}; - -enum -{ - CDC_LINE_CODING_PARITY_NONE = 0, - CDC_LINE_CODING_PARITY_ODD = 1, - CDC_LINE_CODING_PARITY_EVEN = 2, - CDC_LINE_CODING_PARITY_MARK = 3, - CDC_LINE_CODING_PARITY_SPACE = 4, -}; - -//--------------------------------------------------------------------+ -// Management Element Notification (Notification Endpoint) -//--------------------------------------------------------------------+ - -/// 6.3 Notification Codes -typedef enum -{ - CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. - CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. - CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, - CDC_NOTIF_RING_DETECT = 0x09, - CDC_NOTIF_SERIAL_STATE = 0x20, - CDC_NOTIF_CALL_STATE_CHANGE = 0x28, - CDC_NOTIF_LINE_STATE_CHANGE = 0x29, - CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred - CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, -}cdc_notification_request_t; - -//--------------------------------------------------------------------+ -// Class Specific Functional Descriptor (Communication Interface) -//--------------------------------------------------------------------+ - -// Start of all packed definitions for compiler without per-type packed -TU_ATTR_PACKED_BEGIN -TU_ATTR_BIT_FIELD_ORDER_BEGIN - -/// Header Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ - uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal -}cdc_desc_func_header_t; - -/// Union Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bControlInterface ; ///< Interface number of Communication Interface - uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface -}cdc_desc_func_union_t; - -#define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t bControlInterface ;\ - uint8_t bSubordinateInterface[no_slave] ;\ -} - -/// Country Selection Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. - uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. -}cdc_desc_func_country_selection_t; - -#define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t iCountryCodeRelDate ;\ - uint16_t wCountryCode[no_country] ;\ -} - -//--------------------------------------------------------------------+ -// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS -//--------------------------------------------------------------------+ - -/// \brief Call Management Functional Descriptor -/// \details This functional descriptor describes the processing of calls for the Communications Class interface. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - - struct { - uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. - uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. - uint8_t TU_RESERVED : 6; - } bmCapabilities; - - uint8_t bDataInterface; -}cdc_desc_func_call_management_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. - uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. - uint8_t support_send_break : 1; ///< Device supports the request Send_Break - uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. - uint8_t TU_RESERVED : 4; -}cdc_acm_capability_t; - -TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); - -/// Abstract Control Management Functional Descriptor -/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - cdc_acm_capability_t bmCapabilities ; -}cdc_desc_func_acm_t; - -/// \brief Direct Line Management Functional Descriptor -/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. - uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. - uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_direct_line_management_t; - -/// \brief Telephone Ringer Functional Descriptor -/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, -/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bRingerVolSteps ; - uint8_t bNumRingerPatterns ; -}cdc_desc_func_telephone_ringer_t; - -/// \brief Telephone Operational Modes Functional Descriptor -/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by -/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t simple_mode : 1; - uint8_t standalone_mode : 1; - uint8_t computer_centric_mode : 1; - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_telephone_operational_modes_t; - -/// \brief Telephone Call and Line State Reporting Capabilities Descriptor -/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a -/// telephone device to report optional call and line states. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone - uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. - uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information. - uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. - uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. - uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification - uint32_t TU_RESERVED0 : 2; - uint32_t TU_RESERVED1 : 16; - uint32_t TU_RESERVED2 : 8; - } bmCapabilities; -}cdc_desc_func_telephone_call_state_reporting_capabilities_t; - -// TODO remove -static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) -{ - return p_desc[2]; -} - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - uint32_t bit_rate; - uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits - uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space - uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 -} cdc_line_coding_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint16_t dtr : 1; - uint16_t rts : 1; - uint16_t : 6; - uint16_t : 8; -} cdc_line_control_state_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); - -TU_ATTR_PACKED_END // End of all packed definitions -TU_ATTR_BIT_FIELD_ORDER_END - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.c deleted file mode 100644 index 5adce521..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_CDC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "cdc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) - uint8_t line_state; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; - TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; - - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; - - OSAL_MUTEX_DEF(rx_ff_mutex); - OSAL_MUTEX_DEF(tx_ff_mutex); - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; - -}cdcd_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; - -static bool _prep_out_transaction (cdcd_interface_t* p_cdc) -{ - uint8_t const rhport = 0; - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if ( available >= sizeof(p_cdc->epout_buf) ) - { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_cdc->ep_out); - - return false; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_cdc_n_connected(uint8_t itf) -{ - // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); -} - -uint8_t tud_cdc_n_get_line_state (uint8_t itf) -{ - return _cdcd_itf[itf].line_state; -} - -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) -{ - (*coding) = _cdcd_itf[itf].line_coding; -} - -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) -{ - _cdcd_itf[itf].wanted_char = wanted; -} - - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_available(uint8_t itf) -{ - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); -} - -uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) bufsize); - _prep_out_transaction(p_cdc); - return num_read; -} - -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) -{ - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); -} - -void tud_cdc_n_read_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(p_cdc); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) bufsize); - - // flush if queue more than packet size - // may need to suppress -Wunreachable-code since most of the time CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - if ( (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE) || ((CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE) && tu_fifo_full(&p_cdc->tx_ff)) ) - { - tud_cdc_n_write_flush(itf); - } - - return ret; -} - -uint32_t tud_cdc_n_write_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); - - // No data to send - if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - - uint8_t const rhport = 0; - - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - - // Pull data from FIFO - uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_cdc->ep_in); - return 0; - } -} - -uint32_t tud_cdc_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); -} - -bool tud_cdc_n_write_clear (uint8_t itf) -{ - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void cdcd_init(void) -{ - tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); - - for(uint8_t i=0; iwanted_char = (char) -1; - - // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; - p_cdc->line_coding.stop_bits = 0; - p_cdc->line_coding.parity = 0; - p_cdc->line_coding.data_bits = 8; - - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - - // Config TX fifo as overwritable at initialization and will be changed to non-overwritable - // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. - // In this way, the most current data is prioritized. - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); - - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); - } -} - -void cdcd_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_cdc->tx_ff); - tu_fifo_set_overwritable(&p_cdc->tx_ff, true); - } -} - -uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - - // Find available interface - cdcd_interface_t * p_cdc = NULL; - for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - } - - // Prepare for incoming data - _prep_out_transaction(p_cdc); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - switch ( request->bRequest ) - { - case CDC_REQUEST_SET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - else if ( stage == CONTROL_STAGE_ACK) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - break; - - case CDC_REQUEST_GET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - break; - - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; - - // Disable fifo overwriting if DTR bit is set - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); - - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } - break; - case CDC_REQUEST_SEND_BREAK: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) - { - p_cdc = &_cdcd_itf[itf]; - if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_CDC); - - // Received new data - if ( ep_addr == p_cdc->ep_out ) - { - tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes); - - // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) - { - for ( uint32_t i = 0; i < xferred_bytes; i++ ) - { - if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) - { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); - } - } - } - - // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); - - // prepare for OUT transaction - _prep_out_transaction(p_cdc); - } - - // Data sent to host, we continue to fetch from tx fifo to send. - // Note: This will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! - if ( ep_addr == p_cdc->ep_in ) - { - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); - - if ( 0 == tud_cdc_n_write_flush(itf) ) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) - { - if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) - { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); - } - } - } - } - - // nothing to do with notif endpoint for now - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.h deleted file mode 100644 index a6e07aa5..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_device.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_DEVICE_H_ -#define _TUSB_CDC_DEVICE_H_ - -#include "cdc.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) - #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE -#endif - -#ifndef CFG_TUD_CDC_EP_BUFSIZE - #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_CDC > 1 -//--------------------------------------------------------------------+ - -// Check if terminal is connected to this port -bool tud_cdc_n_connected (uint8_t itf); - -// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) -uint8_t tud_cdc_n_get_line_state (uint8_t itf); - -// Get current line encoding: bit rate, stop bits parity etc .. -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); - -// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); - -// Get the number of bytes available for reading -uint32_t tud_cdc_n_available (uint8_t itf); - -// Read received bytes -uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); - -// Read a byte, return -1 if there is none -static inline -int32_t tud_cdc_n_read_char (uint8_t itf); - -// Clear the received FIFO -void tud_cdc_n_read_flush (uint8_t itf); - -// Get a byte from FIFO without removing it -bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); - -// Write bytes to TX FIFO, data may remain in the FIFO for a while -uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); - -// Write a byte -static inline -uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); - -// Write a null-terminated string -static inline -uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); - -// Force sending data if possible, return number of forced bytes -uint32_t tud_cdc_n_write_flush (uint8_t itf); - -// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. -uint32_t tud_cdc_n_write_available (uint8_t itf); - -// Clear the transmit FIFO -bool tud_cdc_n_write_clear (uint8_t itf); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_cdc_connected (void); -static inline uint8_t tud_cdc_get_line_state (void); -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); -static inline void tud_cdc_set_wanted_char (char wanted); - -static inline uint32_t tud_cdc_available (void); -static inline int32_t tud_cdc_read_char (void); -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); -static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (uint8_t* ui8); - -static inline uint32_t tud_cdc_write_char (char ch); -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_cdc_write_str (char const* str); -static inline uint32_t tud_cdc_write_flush (void); -static inline uint32_t tud_cdc_write_available (void); -static inline bool tud_cdc_write_clear (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); - -// Invoked when received `wanted_char` -TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); - -// Invoked when a TX is complete and therefore space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); - -// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE -TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); - -// Invoked when line coding is change via SET_LINE_CODING -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); - -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline int32_t tud_cdc_n_read_char (uint8_t itf) -{ - uint8_t ch; - return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; -} - -static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) -{ - return tud_cdc_n_write(itf, &ch, 1); -} - -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str) -{ - return tud_cdc_n_write(itf, str, strlen(str)); -} - -static inline bool tud_cdc_connected (void) -{ - return tud_cdc_n_connected(0); -} - -static inline uint8_t tud_cdc_get_line_state (void) -{ - return tud_cdc_n_get_line_state(0); -} - -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) -{ - tud_cdc_n_get_line_coding(0, coding); -} - -static inline void tud_cdc_set_wanted_char (char wanted) -{ - tud_cdc_n_set_wanted_char(0, wanted); -} - -static inline uint32_t tud_cdc_available (void) -{ - return tud_cdc_n_available(0); -} - -static inline int32_t tud_cdc_read_char (void) -{ - return tud_cdc_n_read_char(0); -} - -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) -{ - return tud_cdc_n_read(0, buffer, bufsize); -} - -static inline void tud_cdc_read_flush (void) -{ - tud_cdc_n_read_flush(0); -} - -static inline bool tud_cdc_peek (uint8_t* ui8) -{ - return tud_cdc_n_peek(0, ui8); -} - -static inline uint32_t tud_cdc_write_char (char ch) -{ - return tud_cdc_n_write_char(0, ch); -} - -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) -{ - return tud_cdc_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_cdc_write_str (char const* str) -{ - return tud_cdc_n_write_str(0, str); -} - -static inline uint32_t tud_cdc_write_flush (void) -{ - return tud_cdc_n_write_flush(0); -} - -static inline uint32_t tud_cdc_write_available(void) -{ - return tud_cdc_n_write_available(0); -} - -static inline bool tud_cdc_write_clear(void) -{ - return tud_cdc_n_write_clear(0); -} - -/** @} */ -/** @} */ - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.c b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.c deleted file mode 100644 index fe3691bf..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_CDC) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "cdc_host.h" - -// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message -#define CDCH_DEBUG 2 - -#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) - -//--------------------------------------------------------------------+ -// Host CDC Interface -//--------------------------------------------------------------------+ - -typedef struct { - uint8_t daddr; - uint8_t bInterfaceNumber; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - - uint8_t serial_drid; // Serial Driver ID - cdc_acm_capability_t acm_capability; - uint8_t ep_notif; - - uint8_t line_state; // DTR (bit0), RTS (bit1) - TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width - - tuh_xfer_cb_t user_control_cb; - - struct { - tu_edpt_stream_t tx; - tu_edpt_stream_t rx; - - uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; - CFG_TUH_MEM_ALIGN uint8_t tx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; - - uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; - CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; - } stream; - -} cdch_interface_t; - -CFG_TUH_MEM_SECTION -static cdch_interface_t cdch_data[CFG_TUH_CDC]; - -//--------------------------------------------------------------------+ -// Serial Driver -//--------------------------------------------------------------------+ - -//------------- ACM prototypes -------------// -static void acm_process_config(tuh_xfer_t* xfer); - -static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - -//------------- FTDI prototypes -------------// -#if CFG_TUH_CDC_FTDI -#include "serial/ftdi_sio.h" - -static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST }; -enum { - FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0]) -}; - -// Store last request baudrate since divisor to baudrate is not easy -static uint32_t _ftdi_requested_baud; - -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); -static void ftdi_process_config(tuh_xfer_t* xfer); - -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif - -//------------- CP210X prototypes -------------// -#if CFG_TUH_CDC_CP210X -#include "serial/cp210x.h" - -static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST }; -enum { - CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0]) -}; - -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -static void cp210x_process_config(tuh_xfer_t* xfer); - -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif - -enum { - SERIAL_DRIVER_ACM = 0, - -#if CFG_TUH_CDC_FTDI - SERIAL_DRIVER_FTDI, -#endif - -#if CFG_TUH_CDC_CP210X - SERIAL_DRIVER_CP210X, -#endif -}; - -typedef struct { - void (*const process_set_config)(tuh_xfer_t* xfer); - bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -} cdch_serial_driver_t; - -// Note driver list must be in the same order as SERIAL_DRIVER enum -static const cdch_serial_driver_t serial_drivers[] = { - { .process_set_config = acm_process_config, - .set_control_line_state = acm_set_control_line_state, - .set_baudrate = acm_set_baudrate - }, - - #if CFG_TUH_CDC_FTDI - { .process_set_config = ftdi_process_config, - .set_control_line_state = ftdi_sio_set_modem_ctrl, - .set_baudrate = ftdi_sio_set_baudrate - }, - #endif - - #if CFG_TUH_CDC_CP210X - { .process_set_config = cp210x_process_config, - .set_control_line_state = cp210x_set_modem_ctrl, - .set_baudrate = cp210x_set_baudrate - }, - #endif -}; - -enum { - SERIAL_DRIVER_COUNT = sizeof(serial_drivers) / sizeof(serial_drivers[0]) -}; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -static inline cdch_interface_t* get_itf(uint8_t idx) -{ - TU_ASSERT(idx < CFG_TUH_CDC, NULL); - cdch_interface_t* p_cdc = &cdch_data[idx]; - - return (p_cdc->daddr != 0) ? p_cdc : NULL; -} - -static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) -{ - for(uint8_t i=0; idaddr == daddr) && - (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) - { - return i; - } - } - - return TUSB_INDEX_INVALID_8; -} - - -static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc) -{ - for(uint8_t i=0; idaddr = daddr; - p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; - p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; - p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; - p_cdc->line_state = 0; - return p_cdc; - } - } - - return NULL; -} - -static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep); -static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num); -static void cdch_internal_control_complete(tuh_xfer_t* xfer); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for(uint8_t i=0; idaddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i; - } - - return TUSB_INDEX_INVALID_8; -} - -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && info); - - info->daddr = p_cdc->daddr; - - // re-construct descriptor - tusb_desc_interface_t* desc = &info->desc; - desc->bLength = sizeof(tusb_desc_interface_t); - desc->bDescriptorType = TUSB_DESC_INTERFACE; - - desc->bInterfaceNumber = p_cdc->bInterfaceNumber; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = 2u + (p_cdc->ep_notif ? 1u : 0u); - desc->bInterfaceClass = TUSB_CLASS_CDC; - desc->bInterfaceSubClass = p_cdc->bInterfaceSubClass; - desc->bInterfaceProtocol = p_cdc->bInterfaceProtocol; - desc->iInterface = 0; // not used yet - - return true; -} - -bool tuh_cdc_mounted(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - return p_cdc != NULL; -} - -bool tuh_cdc_get_dtr(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false; -} - -bool tuh_cdc_get_rts(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false; -} - -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - *line_coding = p_cdc->line_coding; - - return true; -} - -//--------------------------------------------------------------------+ -// Write -//--------------------------------------------------------------------+ - -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); -} - -uint32_t tuh_cdc_write_flush(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); -} - -bool tuh_cdc_write_clear(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_clear(&p_cdc->stream.tx); -} - -uint32_t tuh_cdc_write_available(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_write_available(&p_cdc->stream.tx); -} - -//--------------------------------------------------------------------+ -// Read -//--------------------------------------------------------------------+ - -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); -} - -uint32_t tuh_cdc_read_available(uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_read_available(&p_cdc->stream.rx); -} - -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - return tu_edpt_stream_peek(&p_cdc->stream.rx, ch); -} - -bool tuh_cdc_read_clear (uint8_t idx) -{ - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); - tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - return ret; -} - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -// internal control complete to update state such as line state, encoding -static void cdch_internal_control_complete(tuh_xfer_t* xfer) -{ - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - - if (xfer->result == XFER_RESULT_SUCCESS) - { - switch (p_cdc->serial_drid) { - case SERIAL_DRIVER_ACM: - switch (xfer->setup->bRequest) { - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); - break; - - case CDC_REQUEST_SET_LINE_CODING: { - uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); - memcpy(&p_cdc->line_coding, xfer->buffer, len); - } - break; - - default: break; - } - break; - - #if CFG_TUH_CDC_FTDI - case SERIAL_DRIVER_FTDI: - switch (xfer->setup->bRequest) { - case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); - break; - - case FTDI_SIO_SET_BAUD_RATE: - // convert from divisor to baudrate is not supported - p_cdc->line_coding.bit_rate = _ftdi_requested_baud; - break; - - default: break; - } - break; - #endif - - #if CFG_TUH_CDC_CP210X - case SERIAL_DRIVER_CP210X: - switch(xfer->setup->bRequest) { - case CP210X_SET_MHS: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); - break; - - case CP210X_SET_BAUDRATE: { - uint32_t baudrate; - memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); - p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); - } - break; - } - break; - #endif - - default: break; - } - } - - xfer->complete_cb = p_cdc->user_control_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); - } -} - -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - - if ( complete_cb ) { - return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); - }else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); - - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - - p_cdc->line_state = (uint8_t) line_state; - return true; - } -} - -bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - - if ( complete_cb ) { - return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); - }else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); - - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - - p_cdc->line_coding.bit_rate = baudrate; - return true; - } -} - -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - cdch_interface_t* p_cdc = get_itf(idx); - // only ACM support this set line coding request - TU_VERIFY(p_cdc && p_cdc->serial_drid == SERIAL_DRIVER_ACM); - TU_VERIFY(p_cdc->acm_capability.support_line_request); - - if ( complete_cb ) { - return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); - }else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = acm_set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); - - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - - p_cdc->line_coding = *line_coding; - return true; - } -} - -//--------------------------------------------------------------------+ -// CLASS-USBH API -//--------------------------------------------------------------------+ - -void cdch_init(void) -{ - tu_memclr(cdch_data, sizeof(cdch_data)); - - for(size_t i=0; istream.tx, true, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); - - tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); - } -} - -void cdch_close(uint8_t daddr) -{ - for(uint8_t idx=0; idxdaddr == daddr) - { - // Invoke application callback - if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); - - //tu_memclr(p_cdc, sizeof(cdch_interface_t)); - p_cdc->daddr = 0; - p_cdc->bInterfaceNumber = 0; - tu_edpt_stream_close(&p_cdc->stream.tx); - tu_edpt_stream_close(&p_cdc->stream.rx); - } - } -} - -bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - // TODO handle stall response, retry failed transfer ... - TU_ASSERT(event == XFER_RESULT_SUCCESS); - - uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc); - - if ( ep_addr == p_cdc->stream.tx.ep_addr ) - { - // invoke tx complete callback to possibly refill tx fifo - if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx); - - if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) - { - // If there is no data left, a ZLP should be sent if: - // - xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); - } - } - else if ( ep_addr == p_cdc->stream.rx.ep_addr ) - { - tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - - #if CFG_TUH_CDC_FTDI - // FTDI reserve 2 bytes for status - if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { - uint8_t status[2]; - tu_edpt_stream_read(&p_cdc->stream.rx, status, 2); - (void) status; // TODO handle status - } - #endif - - // invoke receive callback - if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx); - - // prepare for next transfer if needed - tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - }else if ( ep_addr == p_cdc->ep_notif ) - { - // TODO handle notification endpoint - }else - { - TU_ASSERT(false); - } - - return true; -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ - -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); - -static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) -{ - for(size_t i=0; i<2; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - - TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); - - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { - tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep); - }else - { - tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep); - } - - desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(desc_ep); - } - - return true; -} - -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - (void) rhport; - - // Only support ACM subclass - // Note: Protocol 0xFF can be RNDIS device - if ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) - { - return acm_open(daddr, itf_desc, max_len); - } - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X - else if ( 0xff == itf_desc->bInterfaceClass ) - { - uint16_t vid, pid; - TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); - - #if CFG_TUH_CDC_FTDI - if (TU_FTDI_VID == vid) { - for (size_t i = 0; i < FTDI_PID_COUNT; i++) { - if (ftdi_pids[i] == pid) { - return ftdi_open(daddr, itf_desc, max_len); - } - } - } - #endif - - #if CFG_TUH_CDC_CP210X - if (TU_CP210X_VID == vid) { - for (size_t i = 0; i < CP210X_PID_COUNT; i++) { - if (cp210x_pids[i] == pid) { - return cp210x_open(daddr, itf_desc, max_len); - } - } - } - #endif - } - #endif - - return false; -} - -static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) { - if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx); - - // Prepare for incoming data - tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(p_cdc->daddr, itf_num); -} - - -bool cdch_set_config(uint8_t daddr, uint8_t itf_num) -{ - tusb_control_request_t request; - request.wIndex = tu_htole16((uint16_t) itf_num); - - // fake transfer to kick-off process - tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = 0; // initial state - - uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - - serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); - return true; -} - -//--------------------------------------------------------------------+ -// ACM -//--------------------------------------------------------------------+ - -enum { - CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, - CONFIG_ACM_SET_LINE_CODING, - CONFIG_ACM_COMPLETE, -}; - -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len; - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - p_cdc->serial_drid = SERIAL_DRIVER_ACM; - - //------------- Control Interface -------------// - uint8_t const * p_desc = tu_desc_next(itf_desc); - - // Communication Functional Descriptors - while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { - // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; - } - - p_desc = tu_desc_next(p_desc); - } - - // Open notification endpoint of control interface if any - if (itf_desc->bNumEndpoints == 1) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - p_desc = tu_desc_next(p_desc); - - // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); - } - - return true; -} - -static void acm_process_config(tuh_xfer_t* xfer) -{ - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - - switch(state) - { - case CONFIG_ACM_SET_CONTROL_LINE_STATE: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { - TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, - CONFIG_ACM_SET_LINE_CODING), ); - break; - } - #endif - TU_ATTR_FALLTHROUGH; - - case CONFIG_ACM_SET_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE), ); - break; - } - #endif - TU_ATTR_FALLTHROUGH; - - case CONFIG_ACM_COMPLETE: - // itf_num+1 to account for data interface as well - set_config_complete(p_cdc, idx, itf_num+1); - break; - - default: break; - } -} - -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16(line_state), - .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), - .wLength = 0 - }; - - p_cdc->user_control_cb = complete_cb; - - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call - .user_data = user_data - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; -} - -static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_LINE_CODING, - .wValue = 0, - .wIndex = tu_htole16(p_cdc->bInterfaceNumber), - .wLength = tu_htole16(sizeof(cdc_line_coding_t)) - }; - - // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t* enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); - - p_cdc->user_control_cb = complete_cb; - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = enum_buf, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call - .user_data = user_data - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; -} - -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - cdc_line_coding_t line_coding = p_cdc->line_coding; - line_coding.bit_rate = baudrate; - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); -} - -//--------------------------------------------------------------------+ -// FTDI -//--------------------------------------------------------------------+ -#if CFG_TUH_CDC_FTDI - -enum { - CONFIG_FTDI_RESET = 0, - CONFIG_FTDI_MODEM_CTRL, - CONFIG_FTDI_SET_BAUDRATE, - CONFIG_FTDI_SET_DATA, - CONFIG_FTDI_COMPLETE -}; - -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { - // FTDI Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - TU_LOG_CDCH("FTDI opened\r\n"); - - p_cdc->serial_drid = SERIAL_DRIVER_FTDI; - - // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); -} - -// set request without data -static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_VENDOR, - .direction = TUSB_DIR_OUT - }, - .bRequest = command, - .wValue = tu_htole16(value), - .wIndex = 0, - .wLength = 0 - }; - - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data); -} - -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n"); - p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, - complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} - -static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) -{ - const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; - uint32_t divisor; - - /* divisor shifted 3 bits to the left */ - uint32_t divisor3 = base / (2 * baud); - divisor = (divisor3 >> 3); - divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; - - /* Deal with special cases for highest baud rates. */ - if (divisor == 1) { /* 1.0 */ - divisor = 0; - } - else if (divisor == 0x4001) { /* 1.5 */ - divisor = 1; - } - - return divisor; -} - -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) -{ - return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); -} - -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); - - p_cdc->user_control_cb = complete_cb; - _ftdi_requested_baud = baudrate; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, - complete_cb ? cdch_internal_control_complete : NULL, user_data)); - - return true; -} - -static void ftdi_process_config(tuh_xfer_t* xfer) { - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - - switch(state) { - // Note may need to read FTDI eeprom - case CONFIG_FTDI_RESET: - TU_ASSERT(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL),); - break; - - case CONFIG_FTDI_MODEM_CTRL: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_FTDI_SET_BAUDRATE: { - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, ftdi_process_config, CONFIG_FTDI_SET_DATA),); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - } - - case CONFIG_FTDI_SET_DATA: { - #if 0 // TODO set data format - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(ftdi_sio_set_data(p_cdc, process_ftdi_config, CONFIG_FTDI_COMPLETE),); - break; - #endif - #endif - - TU_ATTR_FALLTHROUGH; - } - - case CONFIG_FTDI_COMPLETE: - set_config_complete(p_cdc, idx, itf_num); - break; - - default: - break; - } -} - -#endif - -//--------------------------------------------------------------------+ -// CP210x -//--------------------------------------------------------------------+ - -#if CFG_TUH_CDC_CP210X - -enum { - CONFIG_CP210X_IFC_ENABLE = 0, - CONFIG_CP210X_SET_BAUDRATE, - CONFIG_CP210X_SET_LINE_CTL, - CONFIG_CP210X_SET_DTR_RTS, - CONFIG_CP210X_COMPLETE -}; - -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // CP210x Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - TU_LOG_CDCH("CP210x opened\r\n"); - p_cdc->serial_drid = SERIAL_DRIVER_CP210X; - - // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); -} - -static bool cp210x_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_VENDOR, - .direction = TUSB_DIR_OUT - }, - .bRequest = command, - .wValue = tu_htole16(value), - .wIndex = p_cdc->bInterfaceNumber, - .wLength = tu_htole16(length) - }; - - // use usbh enum buf since application variable does not live long enough - uint8_t* enum_buf = NULL; - - if (buffer && length > 0) { - enum_buf = usbh_get_enum_buf(); - tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); - } - - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = enum_buf, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); -} - -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); - uint32_t baud_le = tu_htole32(baudrate); - p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, - complete_cb ? cdch_internal_control_complete : NULL, user_data); -} - -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n"); - p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, - complete_cb ? cdch_internal_control_complete : NULL, user_data); -} - -static void cp210x_process_config(tuh_xfer_t* xfer) { - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); - - switch (state) { - case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE),); - break; - - case CONFIG_CP210X_SET_BAUDRATE: { - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - } - - case CONFIG_CP210X_SET_LINE_CTL: { - #if defined(CFG_TUH_CDC_LINE_CODING_ON_ENUM) && 0 // skip for now - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - } - - case CONFIG_CP210X_SET_DTR_RTS: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_CP210X_COMPLETE: - set_config_complete(p_cdc, idx, itf_num); - break; - - default: break; - } -} - -#endif - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.h deleted file mode 100644 index 19552f1e..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_host.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// Set Line Control state on enumeration/mounted: DTR ( bit 0), RTS (bit 1) -#ifndef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM -#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0 -#endif - -// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t -//#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM -//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } -//#endif - -// RX FIFO size -#ifndef CFG_TUH_CDC_RX_BUFSIZE -#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX -#endif - -// RX Endpoint size -#ifndef CFG_TUH_CDC_RX_EPSIZE -#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX -#endif - -// TX FIFO size -#ifndef CFG_TUH_CDC_TX_BUFSIZE -#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX -#endif - -// TX Endpoint size -#ifndef CFG_TUH_CDC_TX_EPSIZE -#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Get Interface index from device address + interface number -// return TUSB_INDEX_INVALID_8 (0xFF) if not found -uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num); - -// Get Interface information -// return true if index is correct and interface is currently mounted -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info); - -// Check if a interface is mounted -bool tuh_cdc_mounted(uint8_t idx); - -// Get current DTR status -bool tuh_cdc_get_dtr(uint8_t idx); - -// Get current RTS status -bool tuh_cdc_get_rts(uint8_t idx); - -// Check if interface is connected (DTR active) -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) -{ - return tuh_cdc_get_dtr(idx); -} - -// Get local (saved/cached) version of line coding. -// This function should return correct values if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() -// are invoked previously or CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined. -// NOTE: This function does not make any USB transfer request to device. -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding); - -//--------------------------------------------------------------------+ -// Write API -//--------------------------------------------------------------------+ - -// Get the number of bytes available for writing -uint32_t tuh_cdc_write_available(uint8_t idx); - -// Write to cdc interface -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize); - -// Force sending data if possible, return number of forced bytes -uint32_t tuh_cdc_write_flush(uint8_t idx); - -// Clear the transmit FIFO -bool tuh_cdc_write_clear(uint8_t idx); - -//--------------------------------------------------------------------+ -// Read API -//--------------------------------------------------------------------+ - -// Get the number of bytes available for reading -uint32_t tuh_cdc_read_available(uint8_t idx); - -// Read from cdc interface -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize); - -// Get a byte from RX FIFO without removing it -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch); - -// Clear the received FIFO -bool tuh_cdc_read_clear (uint8_t idx); - -//--------------------------------------------------------------------+ -// Control Endpoint (Request) API -// Each Function will make a USB control transfer request to/from device -// - If complete_cb is provided, the function will return immediately and invoke -// the callback when request is complete. -// - If complete_cb is NULL, the function will block until request is complete. -// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result. -// - The function will return true if transfer is successful, false otherwise. -//--------------------------------------------------------------------+ - -// Request to Set Control Line State: DTR (bit 0), RTS (bit 1) -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - -// Request to set baudrate -bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - -// Request to Set Line Coding (ACM only) -// Should only use if you don't work with serial devices such as FTDI/CP210x -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - -// Request to Get Line Coding (ACM only) -// Should only use if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() never got invoked and -// CFG_TUH_CDC_LINE_CODING_ON_ENUM is not defined -// bool tuh_cdc_get_line_coding(uint8_t idx, cdc_line_coding_t* coding); - -// Connect by set both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); -} - -// Disconnect by clear both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); -} - -//--------------------------------------------------------------------+ -// CDC APPLICATION CALLBACKS -//--------------------------------------------------------------------+ - -// Invoked when a device with CDC interface is mounted -// idx is index of cdc interface in the internal pool. -TU_ATTR_WEAK extern void tuh_cdc_mount_cb(uint8_t idx); - -// Invoked when a device with CDC interface is unmounted -TU_ATTR_WEAK extern void tuh_cdc_umount_cb(uint8_t idx); - -// Invoked when received new data -TU_ATTR_WEAK extern void tuh_cdc_rx_cb(uint8_t idx); - -// Invoked when a TX is complete and therefore space becomes available in TX buffer -TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cdch_init (void); -bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_HOST_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis.h deleted file mode 100644 index ad153e0a..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup ClassDriver_CDC Communication Device Class (CDC) - * \defgroup CDC_RNDIS Remote Network Driver Interface Specification (RNDIS) - * @{ - * \defgroup CDC_RNDIS_Common Common Definitions - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __CC_ARM -#pragma diag_suppress 66 // Suppress Keil warnings #66-D: enumeration value is out of "int" range -#endif - -/// RNDIS Message Types -typedef enum -{ - RNDIS_MSG_PACKET = 0x00000001UL, ///< The host and device use this to send network data to one another. - - RNDIS_MSG_INITIALIZE = 0x00000002UL, ///< Sent by the host to initialize the device. - RNDIS_MSG_INITIALIZE_CMPLT = 0x80000002UL, ///< Device response to an initialize message. - - RNDIS_MSG_HALT = 0x00000003UL, ///< Sent by the host to halt the device. This does not have a response. It is optional for the device to send this message to the host. - - RNDIS_MSG_QUERY = 0x00000004UL, ///< Sent by the host to send a query OID. - RNDIS_MSG_QUERY_CMPLT = 0x80000004UL, ///< Device response to a query OID. - - RNDIS_MSG_SET = 0x00000005UL, ///< Sent by the host to send a set OID. - RNDIS_MSG_SET_CMPLT = 0x80000005UL, ///< Device response to a set OID. - - RNDIS_MSG_RESET = 0x00000006UL, ///< Sent by the host to perform a soft reset on the device. - RNDIS_MSG_RESET_CMPLT = 0x80000006UL, ///< Device response to reset message. - - RNDIS_MSG_INDICATE_STATUS = 0x00000007UL, ///< Sent by the device to indicate its status or an error when an unrecognized message is received. - - RNDIS_MSG_KEEP_ALIVE = 0x00000008UL, ///< During idle periods, sent every few seconds by the host to check that the device is still responsive. It is optional for the device to send this message to check if the host is active. - RNDIS_MSG_KEEP_ALIVE_CMPLT = 0x80000008UL ///< The device response to a keepalivemessage. The host can respond with this message to a keepalive message from the device when the device implements the optional KeepAliveTimer. -}rndis_msg_type_t; - -/// RNDIS Message Status Values -typedef enum -{ - RNDIS_STATUS_SUCCESS = 0x00000000UL, ///< Success - RNDIS_STATUS_FAILURE = 0xC0000001UL, ///< Unspecified error - RNDIS_STATUS_INVALID_DATA = 0xC0010015UL, ///< Invalid data error - RNDIS_STATUS_NOT_SUPPORTED = 0xC00000BBUL, ///< Unsupported request error - RNDIS_STATUS_MEDIA_CONNECT = 0x4001000BUL, ///< Device is connected to a network medium. - RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000CUL ///< Device is disconnected from the medium. -}rndis_msg_status_t; - -#ifdef __CC_ARM -#pragma diag_default 66 // return Keil 66 to normal severity -#endif - -//--------------------------------------------------------------------+ -// MESSAGE STRUCTURE -//--------------------------------------------------------------------+ - -//------------- Initialize -------------// -/// \brief Initialize Message -/// \details This message MUST be sent by the host to initialize the device. -typedef struct { - uint32_t type ; ///< Message type, must be \ref RNDIS_MSG_INITIALIZE - uint32_t length ; ///< Message length in bytes, must be 0x18 - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t major_version ; ///< The major version of the RNDIS Protocol implemented by the host. - uint32_t minor_version ; ///< The minor version of the RNDIS Protocol implemented by the host - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the host expects to receive from the device. -}rndis_msg_initialize_t; - -/// \brief Initialize Complete Message -/// \details This message MUST be sent by the device in response to an initialize message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_INITIALIZE_CMPLT - uint32_t length ; ///< Message length in bytes, must be 0x30 - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_initialize_t to which this message is a response. - uint32_t status ; ///< The initialization status of the device, has value from \ref rndis_msg_status_t - uint32_t major_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t minor_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t device_flags ; ///< MUST be set to 0x000000010. Other values are reserved for future use. - uint32_t medium ; ///< is 0x00 for RNDIS_MEDIUM_802_3 - uint32_t max_packet_per_xfer ; ///< The maximum number of concatenated \ref RNDIS_MSG_PACKET messages that the device can handle in a single bus transfer to it. This value MUST be at least 1. - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the device expects to receive from the host. - uint32_t packet_alignment_factor ; ///< The byte alignment the device expects for each RNDIS message that is part of a multimessage transfer to it. The value is specified as an exponent of 2; for example, the host uses 2{PacketAlignmentFactor} as the alignment value. - uint32_t reserved[2] ; -} rndis_msg_initialize_cmplt_t; - -//------------- Query -------------// -/// \brief Query Message -/// \details This message MUST be sent by the host to query an OID. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t oid ; ///< The integer value of the host operating system-defined identifier, for the parameter of the device being queried for. - uint32_t buffer_length ; ///< The length, in bytes, of the input data required for the OID query. This MUST be set to 0 when there is no input data associated with the OID. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the input data for the query is located in the message. This value MUST be set to 0 when there is no input data associated with the OID. - uint32_t reserved ; - uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. -} rndis_msg_query_t, rndis_msg_set_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); - -/// \brief Query Complete Message -/// \details This message MUST be sent by the device in response to a query OID message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY_CMPLT - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_query_t to which this message is a response. - uint32_t status ; ///< The status of processing for the query request, has value from \ref rndis_msg_status_t. - uint32_t buffer_length ; ///< The length, in bytes, of the data in the response to the query. This MUST be set to 0 when there is no OIDInputBuffer. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the response data for the query is located in the message. This MUST be set to 0 when there is no \ref oid_buffer. - uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. -} rndis_msg_query_cmplt_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); - -//------------- Reset -------------// -/// \brief Reset Message -/// \details This message MUST be sent by the host to perform a soft reset on the device. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET - uint32_t length ; ///< Message length in bytes, MUST be 0x06 - uint32_t reserved ; -} rndis_msg_reset_t; - -/// \brief Reset Complete Message -/// \details This message MUST be sent by the device in response to a reset message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET_CMPLT - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t status ; ///< The status of processing for the \ref rndis_msg_reset_t, has value from \ref rndis_msg_status_t. - uint32_t addressing_reset ; ///< This field indicates whether the addressing information, which is the multicast address list or packet filter, has been lost during the reset operation. This MUST be set to 0x00000001 if the device requires that the host to resend addressing information or MUST be set to zero otherwise. -} rndis_msg_reset_cmplt_t; - -//typedef struct { -// uint32_t type; -// uint32_t length; -// uint32_t status; -// uint32_t buffer_length; -// uint32_t buffer_offset; -// uint32_t diagnostic_status; // optional -// uint32_t diagnostic_error_offset; // optional -// uint32_t status_buffer[0]; // optional -//} rndis_msg_indicate_status_t; - -/// \brief Keep Alive Message -/// \details This message MUST be sent by the host to check that device is still responsive. It is optional for the device to send this message to check if the host is active -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; -} rndis_msg_keep_alive_t, rndis_msg_halt_t; - -/// \brief Set Complete Message -/// \brief This message MUST be sent in response to a the request message -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; ///< must be the same as requesting message - uint32_t status ; ///< The status of processing for the request message request by the device to which this message is the response. -} rndis_msg_set_cmplt_t, rndis_msg_keep_alive_cmplt_t; - -/// \brief Packet Data Message -/// \brief This message MUST be used by the host and the device to send network data to one another. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_PACKET - uint32_t length ; ///< Message length in bytes, The total length of this RNDIS message including the header, payload, and padding. - uint32_t data_offset ; ///< Specifies the offset, in bytes, from the start of this \a data_offset field of this message to the start of the data. This MUST be an integer multiple of 4. - uint32_t data_length ; ///< Specifies the number of bytes in the payload of this message. - uint32_t out_of_band_data_offet ; ///< Specifies the offset, in bytes, of the first out-of-band data record from the start of the DataOffset field in this message. MUST be an integer multiple of 4 when out-of-band data is present or set to 0 otherwise. When there are multiple out-ofband data records, each subsequent record MUST immediately follow the previous out-of-band data record. - uint32_t out_of_band_data_length ; ///< Specifies, in bytes, the total length of the out-of-band data. - uint32_t num_out_of_band_data_elements ; ///< Specifies the number of out-of-band records in this message. - uint32_t per_packet_info_offset ; ///< Specifies the offset, in bytes, of the start of per-packet-info data record from the start of the \a data_offset field in this message. MUST be an integer multiple of 4 when per-packet-info data record is present or MUST be set to 0 otherwise. When there are multiple per-packet-info data records, each subsequent record MUST immediately follow the previous record. - uint32_t per_packet_info_length ; ///< Specifies, in bytes, the total length of per-packetinformation contained in this message. - uint32_t reserved[2] ; - uint32_t payload[0] ; ///< Network data contained in this message. - - // uint8_t padding[0] - // Additional bytes of zeros added at the end of the message to comply with - // the internal and external padding requirements. Internal padding SHOULD be as per the - // specification of the out-of-band data record and per-packet-info data record. The external - //padding size SHOULD be determined based on the PacketAlignmentFactor field specification - //in REMOTE_NDIS_INITIALIZE_CMPLT message by the device, when multiple - //REMOTE_NDIS_PACKET_MSG messages are bundled together in a single bus-native message. - //In this case, all but the very last REMOTE_NDIS_PACKET_MSG MUST respect the - //PacketAlignmentFactor field. - - // rndis_msg_packet_t [0] : (optional) more packet if multiple packet per bus transaction is supported -} rndis_msg_packet_t; - - -typedef struct { - uint32_t size ; ///< Length, in bytes, of this header and appended data and padding. This value MUST be an integer multiple of 4. - uint32_t type ; ///< MUST be as per host operating system specification. - uint32_t offset ; ///< The byte offset from the beginning of this record to the beginning of data. - uint32_t data[0] ; ///< Flexible array contains data -} rndis_msg_out_of_band_data_t, rndis_msg_per_packet_info_t; - -//--------------------------------------------------------------------+ -// NDIS Object ID -//--------------------------------------------------------------------+ - -/// NDIS Object ID -typedef enum -{ - //------------- General Required OIDs -------------// - RNDIS_OID_GEN_SUPPORTED_LIST = 0x00010101, ///< List of supported OIDs - RNDIS_OID_GEN_HARDWARE_STATUS = 0x00010102, ///< Hardware status - RNDIS_OID_GEN_MEDIA_SUPPORTED = 0x00010103, ///< Media types supported (encoded) - RNDIS_OID_GEN_MEDIA_IN_USE = 0x00010104, ///< Media types in use (encoded) - RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD = 0x00010105, ///< - RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE = 0x00010106, ///< Maximum frame size in bytes - RNDIS_OID_GEN_LINK_SPEED = 0x00010107, ///< Link speed in units of 100 bps - RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE = 0x00010108, ///< Transmit buffer space - RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE = 0x00010109, ///< Receive buffer space - RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE = 0x0001010A, ///< Minimum amount of storage, in bytes, that a single packet occupies in the transmit buffer space of the NIC - RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE = 0x0001010B, ///< Amount of storage, in bytes, that a single packet occupies in the receive buffer space of the NIC - RNDIS_OID_GEN_VENDOR_ID = 0x0001010C, ///< Vendor NIC code - RNDIS_OID_GEN_VENDOR_DESCRIPTION = 0x0001010D, ///< Vendor network card description - RNDIS_OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E, ///< Current packet filter (encoded) - RNDIS_OID_GEN_CURRENT_LOOKAHEAD = 0x0001010F, ///< Current lookahead size in bytes - RNDIS_OID_GEN_DRIVER_VERSION = 0x00010110, ///< NDIS version number used by the driver - RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE = 0x00010111, ///< Maximum total packet length in bytes - RNDIS_OID_GEN_PROTOCOL_OPTIONS = 0x00010112, ///< Optional protocol flags (encoded) - RNDIS_OID_GEN_MAC_OPTIONS = 0x00010113, ///< Optional NIC flags (encoded) - RNDIS_OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114, ///< Whether the NIC is connected to the network - RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS = 0x00010115, ///< The maximum number of send packets the driver can accept per call to its MiniportSendPacketsfunction - - //------------- General Optional OIDs -------------// - RNDIS_OID_GEN_VENDOR_DRIVER_VERSION = 0x00010116, ///< Vendor-assigned version number of the driver - RNDIS_OID_GEN_SUPPORTED_GUIDS = 0x00010117, ///< The custom GUIDs (Globally Unique Identifier) supported by the miniport driver - RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES = 0x00010118, ///< List of network-layer addresses associated with the binding between a transport and the driver - RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET = 0x00010119, ///< Size of packets' additional headers - RNDIS_OID_GEN_MEDIA_CAPABILITIES = 0x00010201, ///< - RNDIS_OID_GEN_PHYSICAL_MEDIUM = 0x00010202, ///< Physical media supported by the miniport driver (encoded) - - //------------- 802.3 Objects (Ethernet) -------------// - RNDIS_OID_802_3_PERMANENT_ADDRESS = 0x01010101, ///< Permanent station address - RNDIS_OID_802_3_CURRENT_ADDRESS = 0x01010102, ///< Current station address - RNDIS_OID_802_3_MULTICAST_LIST = 0x01010103, ///< Current multicast address list - RNDIS_OID_802_3_MAXIMUM_LIST_SIZE = 0x01010104, ///< Maximum size of multicast address list -} rndis_oid_type_t; - -/// RNDIS Packet Filter Bits \ref RNDIS_OID_GEN_CURRENT_PACKET_FILTER. -typedef enum -{ - RNDIS_PACKET_TYPE_DIRECTED = 0x00000001, ///< Directed packets. Directed packets contain a destination address equal to the station address of the NIC. - RNDIS_PACKET_TYPE_MULTICAST = 0x00000002, ///< Multicast address packets sent to addresses in the multicast address list. - RNDIS_PACKET_TYPE_ALL_MULTICAST = 0x00000004, ///< All multicast address packets, not just the ones enumerated in the multicast address list. - RNDIS_PACKET_TYPE_BROADCAST = 0x00000008, ///< Broadcast packets. - RNDIS_PACKET_TYPE_SOURCE_ROUTING = 0x00000010, ///< All source routing packets. If the protocol driver sets this bit, the NDIS library attempts to act as a source routing bridge. - RNDIS_PACKET_TYPE_PROMISCUOUS = 0x00000020, ///< Specifies all packets regardless of whether VLAN filtering is enabled or not and whether the VLAN identifier matches or not. - RNDIS_PACKET_TYPE_SMT = 0x00000040, ///< SMT packets that an FDDI NIC receives. - RNDIS_PACKET_TYPE_ALL_LOCAL = 0x00000080, ///< All packets sent by installed protocols and all packets indicated by the NIC that is identified by a given NdisBindingHandle. - RNDIS_PACKET_TYPE_GROUP = 0x00001000, ///< Packets sent to the current group address. - RNDIS_PACKET_TYPE_ALL_FUNCTIONAL = 0x00002000, ///< All functional address packets, not just the ones in the current functional address. - RNDIS_PACKET_TYPE_FUNCTIONAL = 0x00004000, ///< Functional address packets sent to addresses included in the current functional address. - RNDIS_PACKET_TYPE_MAC_FRAME = 0x00008000, ///< NIC driver frames that a Token Ring NIC receives. - RNDIS_PACKET_TYPE_NO_LOCAL = 0x00010000, -} rndis_packet_filter_type_t; - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_H_ */ - -/** @} */ -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.c b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.c deleted file mode 100644 index 11a5355a..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "cdc_host.h" -#include "cdc_rndis_host.h" - -#if 0 // TODO remove subtask related macros later -// Sub Task -#define OSAL_SUBTASK_BEGIN -#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; - -#define STASK_RETURN(_error) return _error; -#define STASK_INVOKE(_subtask, _status) (_status) = _subtask -#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define RNDIS_MSG_PAYLOAD_MAX (1024*4) - -CFG_TUH_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; - -static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; - -// TODO Microsoft requires message length for any get command must be at least 4096 bytes - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static tusb_error_t rndis_body_subtask(void); -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response ); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) -{ - TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); - - memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper -// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with -// forever loop cannot have any return at all. -OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) -{ - OSAL_TASK_BEGIN - rndis_body_subtask(); - OSAL_TASK_END -} - -static tusb_error_t rndis_body_subtask(void) -{ - static uint8_t relative_addr; - - OSAL_SUBTASK_BEGIN - - for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) - { - - } - - osal_task_delay(100); - - OSAL_SUBTASK_END -} - -//--------------------------------------------------------------------+ -// RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -void rndish_init(void) -{ - tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); - - //------------- Task creation -------------// - - //------------- semaphore creation for notification pipe -------------// - for(uint8_t i=0; itype == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && - p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); - rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - - //------------- Message Query 802.3 Permanent Address -------------// - memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_query_t) + 6, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; - STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); - memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); - - //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// - memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags - ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_set_t) + 4, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; - STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); - - tusbh_cdc_rndis_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) - { - osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); - } -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Send RNDIS Control Message -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - mess_length, p_mess), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - //------------- waiting for Response Available notification -------------// - (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); - osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); - - //------------- Get RNDIS Message Initialize Complete -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, - RNDIS_MSG_PAYLOAD_MAX, p_response), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - OSAL_SUBTASK_END -} - -//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -//{ -// tusb_error_t error; -// -// OSAL_SUBTASK_BEGIN -// -// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) -// { -// .type = RNDIS_MSG_INITIALIZE, -// .length = sizeof(rndis_msg_initialize_t), -// .request_id = 1, // TODO should use some magic number -// .major_version = 1, -// .minor_version = 0, -// .max_xfer_size = 0x4000 // TODO mimic windows -// }; -// -// -// -// OSAL_SUBTASK_END -//} -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.h deleted file mode 100644 index bb431ec1..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/cdc_rndis_host.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup CDC_RNDIS - * \defgroup CDC_RNSID_Host Host - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ - -#include "common/tusb_common.h" -#include "host/usbh.h" -#include "cdc_rndis.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INTERNAL RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -typedef struct { - OSAL_SEM_DEF(semaphore_notification); - osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe - uint32_t max_xfer_size; // got from device's msg initialize complete - uint8_t mac_address[6]; -}rndish_data_t; - -void rndish_init(void); -bool rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); -void rndish_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ - -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/cp210x.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/cp210x.h deleted file mode 100644 index b0141709..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/cp210x.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2023 Ha Thach (thach@tinyusb.org) for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TUSB_CP210X_H -#define TUSB_CP210X_H - -// Protocol details can be found at AN571: CP210x Virtual COM Port Interface -// https://www.silabs.com/documents/public/application-notes/AN571.pdf - -#define TU_CP210X_VID 0x10C4 -#define TU_CP210X_PID_LIST \ - 0xEA60, 0xEA70 - -/* Config request codes */ -#define CP210X_IFC_ENABLE 0x00 -#define CP210X_SET_BAUDDIV 0x01 -#define CP210X_GET_BAUDDIV 0x02 -#define CP210X_SET_LINE_CTL 0x03 // Set parity, data bits, stop bits -#define CP210X_GET_LINE_CTL 0x04 -#define CP210X_SET_BREAK 0x05 -#define CP210X_IMM_CHAR 0x06 -#define CP210X_SET_MHS 0x07 // Set DTR, RTS -#define CP210X_GET_MDMSTS 0x08 // Get modem status (DTR, RTS, CTS, DSR, RI, DCD) -#define CP210X_SET_XON 0x09 -#define CP210X_SET_XOFF 0x0A -#define CP210X_SET_EVENTMASK 0x0B -#define CP210X_GET_EVENTMASK 0x0C -#define CP210X_SET_CHAR 0x0D -#define CP210X_GET_CHARS 0x0E -#define CP210X_GET_PROPS 0x0F -#define CP210X_GET_COMM_STATUS 0x10 -#define CP210X_RESET 0x11 -#define CP210X_PURGE 0x12 -#define CP210X_SET_FLOW 0x13 -#define CP210X_GET_FLOW 0x14 -#define CP210X_EMBED_EVENTS 0x15 -#define CP210X_GET_EVENTSTATE 0x16 -#define CP210X_SET_CHARS 0x19 -#define CP210X_GET_BAUDRATE 0x1D -#define CP210X_SET_BAUDRATE 0x1E -#define CP210X_VENDOR_SPECIFIC 0xFF // GPIO, Recipient must be Device - -#endif //TUSB_CP210X_H diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h b/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h deleted file mode 100644 index 6916e403..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/cdc/serial/ftdi_sio.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2023 Ha Thach (thach@tinyusb.org) for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TUSB_FTDI_SIO_H -#define TUSB_FTDI_SIO_H - -// VID/PID for matching FTDI devices -#define TU_FTDI_VID 0x0403 -#define TU_FTDI_PID_LIST \ - 0x6001, 0x6006, 0x6010, 0x6011, 0x6014, 0x6015, 0x8372, 0xFBFA, \ - 0xcd18 - -// Commands -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ -#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ -#define FTDI_SIO_GET_LATENCY_TIMER 0x0a /* Get the latency timer */ -#define FTDI_SIO_SET_BITMODE 0x0b /* Set bitbang mode */ -#define FTDI_SIO_READ_PINS 0x0c /* Read immediate value of pins */ -#define FTDI_SIO_READ_EEPROM 0x90 /* Read EEPROM */ - -/* FTDI_SIO_RESET */ -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_RESET - * wValue: Control Value - * 0 = Reset SIO - * 1 = Purge RX buffer - * 2 = Purge TX buffer - * wIndex: Port - * wLength: 0 - * Data: None - * - * The Reset SIO command has this effect: - * - * Sets flow control set to 'none' - * Event char = $0D - * Event trigger = disabled - * Purge RX buffer - * Purge TX buffer - * Clear DTR - * Clear RTS - * baud and data format not reset - * - * The Purge RX and TX buffer commands affect nothing except the buffers - * - */ - -/* FTDI_SIO_MODEM_CTRL */ -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_MODEM_CTRL - * wValue: ControlValue (see below) - * wIndex: Port - * wLength: 0 - * Data: None - * - * NOTE: If the device is in RTS/CTS flow control, the RTS set by this - * command will be IGNORED without an error being returned - * Also - you can not set DTR and RTS with one control message - */ - -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) -#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2) -#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0) - -/* - * ControlValue - * B0 DTR state - * 0 = reset - * 1 = set - * B1 RTS state - * 0 = reset - * 1 = set - * B2..7 Reserved - * B8 DTR state enable - * 0 = ignore - * 1 = use DTR state - * B9 RTS state enable - * 0 = ignore - * 1 = use RTS state - * B10..15 Reserved - */ - -/* FTDI_SIO_SET_FLOW_CTRL */ -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) -#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) -#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_FLOW_CTRL - * wValue: Xoff/Xon - * wIndex: Protocol/Port - hIndex is protocol / lIndex is port - * wLength: 0 - * Data: None - * - * hIndex protocol is: - * B0 Output handshaking using RTS/CTS - * 0 = disabled - * 1 = enabled - * B1 Output handshaking using DTR/DSR - * 0 = disabled - * 1 = enabled - * B2 Xon/Xoff handshaking - * 0 = disabled - * 1 = enabled - * - * A value of zero in the hIndex field disables handshaking - * - * If Xon/Xoff handshaking is specified, the hValue field should contain the - * XOFF character and the lValue field contains the XON character. - */ - -/* FTDI_SIO_SET_BAUD_RATE */ -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_BAUDRATE - * wValue: BaudDivisor value - see below - * wIndex: Port - * wLength: 0 - * Data: None - * The BaudDivisor values are calculated as follows (too complicated): - */ - -/* FTDI_SIO_SET_DATA */ -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_DATA - * wValue: Data characteristics (see below) - * wIndex: Port - * wLength: 0 - * Data: No - * - * Data characteristics - * - * B0..7 Number of data bits - * B8..10 Parity - * 0 = None - * 1 = Odd - * 2 = Even - * 3 = Mark - * 4 = Space - * B11..13 Stop Bits - * 0 = 1 - * 1 = 1.5 - * 2 = 2 - * B14 - * 1 = TX ON (break) - * 0 = TX OFF (normal state) - * B15 Reserved - * - */ - -/* -* DATA FORMAT -* -* IN Endpoint -* -* The device reserves the first two bytes of data on this endpoint to contain -* the current values of the modem and line status registers. In the absence of -* data, the device generates a message consisting of these two status bytes - * every 40 ms - * - * Byte 0: Modem Status -* -* Offset Description -* B0 Reserved - must be 1 -* B1 Reserved - must be 0 -* B2 Reserved - must be 0 -* B3 Reserved - must be 0 -* B4 Clear to Send (CTS) -* B5 Data Set Ready (DSR) -* B6 Ring Indicator (RI) -* B7 Receive Line Signal Detect (RLSD) -* -* Byte 1: Line Status -* -* Offset Description -* B0 Data Ready (DR) -* B1 Overrun Error (OE) -* B2 Parity Error (PE) -* B3 Framing Error (FE) -* B4 Break Interrupt (BI) -* B5 Transmitter Holding Register (THRE) -* B6 Transmitter Empty (TEMT) -* B7 Error in RCVR FIFO -* -*/ -#define FTDI_RS0_CTS (1 << 4) -#define FTDI_RS0_DSR (1 << 5) -#define FTDI_RS0_RI (1 << 6) -#define FTDI_RS0_RLSD (1 << 7) - -#define FTDI_RS_DR 1 -#define FTDI_RS_OE (1<<1) -#define FTDI_RS_PE (1<<2) -#define FTDI_RS_FE (1<<3) -#define FTDI_RS_BI (1<<4) -#define FTDI_RS_THRE (1<<5) -#define FTDI_RS_TEMT (1<<6) -#define FTDI_RS_FIFO (1<<7) - -#endif //TUSB_FTDI_SIO_H diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu.h b/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu.h deleted file mode 100644 index 114c827b..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ - -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 0x01, - DFU_PROTOCOL_DFU = 0x02, -} dfu_protocol_type_t; - -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; - -// DFU Requests -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; - -// DFU States -typedef enum { - APP_IDLE = 0, - APP_DETACH = 1, - DFU_IDLE = 2, - DFU_DNLOAD_SYNC = 3, - DFU_DNBUSY = 4, - DFU_DNLOAD_IDLE = 5, - DFU_MANIFEST_SYNC = 6, - DFU_MANIFEST = 7, - DFU_MANIFEST_WAIT_RESET = 8, - DFU_UPLOAD_IDLE = 9, - DFU_ERROR = 10, -} dfu_state_t; - -// DFU Status -typedef enum { - DFU_STATUS_OK = 0x00, - DFU_STATUS_ERR_TARGET = 0x01, - DFU_STATUS_ERR_FILE = 0x02, - DFU_STATUS_ERR_WRITE = 0x03, - DFU_STATUS_ERR_ERASE = 0x04, - DFU_STATUS_ERR_CHECK_ERASED = 0x05, - DFU_STATUS_ERR_PROG = 0x06, - DFU_STATUS_ERR_VERIFY = 0x07, - DFU_STATUS_ERR_ADDRESS = 0x08, - DFU_STATUS_ERR_NOTDONE = 0x09, - DFU_STATUS_ERR_FIRMWARE = 0x0A, - DFU_STATUS_ERR_VENDOR = 0x0B, - DFU_STATUS_ERR_USBR = 0x0C, - DFU_STATUS_ERR_POR = 0x0D, - DFU_STATUS_ERR_UNKNOWN = 0x0E, - DFU_STATUS_ERR_STALLEDPKT = 0x0F, -} dfu_status_t; - -#define DFU_ATTR_CAN_DOWNLOAD (1u << 0) -#define DFU_ATTR_CAN_UPLOAD (1u << 1) -#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2) -#define DFU_ATTR_WILL_DETACH (1u << 3) - -// DFU Status Request Payload -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_response_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.c deleted file mode 100644 index 464c4bd6..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_DFU) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t attrs; - uint8_t alt; - - dfu_state_t state; - dfu_status_t status; - - bool flashing_in_progress; - uint16_t block; - uint16_t length; - - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; -} dfu_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx; - -static void reset_state(void) -{ - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.flashing_in_progress = false; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout); -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -tu_static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -tu_static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -tu_static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "ERROR" }, -}; - -tu_static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -tu_static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERR_POR , .data = "errPOR" }, - { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -tu_static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_reset(uint8_t rhport) -{ - (void) rhport; - - _dfu_ctx.attrs = 0; - _dfu_ctx.alt = 0; - - reset_state(); -} - -void dfu_moded_init(void) -{ - dfu_moded_reset(0); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - - //------------- Interface (with Alt) descriptor -------------// - uint8_t const itf_num = itf_desc->bInterfaceNumber; - uint8_t alt_count = 0; - - uint16_t drv_len = 0; - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0); - - while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) - { - TU_ASSERT(max_len > drv_len, 0); - - // Alternate must have the same interface number - TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - - // Alt should increase by one every time - TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); - alt_count++; - - drv_len += tu_desc_len(itf_desc); - itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); - } - - //------------- DFU Functional descriptor -------------// - tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; - TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); - drv_len += sizeof(tusb_desc_dfu_functional_t); - - _dfu_ctx.attrs = func_desc->bAttributes; - - // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); - - if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) - { - // Standard request include GET/SET_INTERFACE - switch ( request->bRequest ) - { - case TUSB_REQ_SET_INTERFACE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // Switch Alt interface and reset state machine - _dfu_ctx.alt = (uint8_t) request->wValue; - reset_state(); - return tud_control_status(rhport, request); - } - break; - - case TUSB_REQ_GET_INTERFACE: - if(stage == CONTROL_STAGE_SETUP) - { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); - } - break; - - // unsupported request - default: return false; - } - } - else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) - { - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - - // Class request - switch ( request->bRequest ) - { - case DFU_REQUEST_DETACH: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); - } - break; - - case DFU_REQUEST_CLRSTATUS: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); - } - break; - - case DFU_REQUEST_ABORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); - } - break; - - case DFU_REQUEST_UPLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); - TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); - } - break; - - case DFU_REQUEST_DNLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); - TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - // set to true for both download and manifest - _dfu_ctx.flashing_in_progress = true; - - // save block and length for flashing - _dfu_ctx.block = request->wValue; - _dfu_ctx.length = request->wLength; - - if ( request->wLength ) - { - // Download with payload -> transition to DOWNLOAD SYNC - _dfu_ctx.state = DFU_DNLOAD_SYNC; - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); - } - else - { - // Download is complete -> transition to MANIFEST SYNC - _dfu_ctx.state = DFU_MANIFEST_SYNC; - return tud_control_status(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - switch ( _dfu_ctx.state ) - { - case DFU_DNLOAD_SYNC: - return process_download_get_status(rhport, stage, request); - break; - - case DFU_MANIFEST_SYNC: - return process_manifest_get_status(rhport, stage, request); - break; - - default: - if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); - break; - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // unsupported request - } - - return true; -} - -void tud_dfu_finish_flashing(uint8_t status) -{ - _dfu_ctx.flashing_in_progress = false; - - if ( status == DFU_STATUS_OK ) - { - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } - else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) - ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; - } - } - else - { - // failed while flashing, move to dfuError - _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = (dfu_status_t)status; - } -} - -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_DNBUSY; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); - } - else - { - next_state = DFU_DNLOAD_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); - }else - { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - } - } - - return true; -} - -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_MANIFEST; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); - } - else - { - next_state = DFU_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_MANIFEST; - tud_dfu_manifest_cb(_dfu_ctx.alt); - } - else - { - _dfu_ctx.state = DFU_IDLE; - } - } - - return true; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) -{ - dfu_status_response_t resp; - resp.bStatus = (uint8_t) status; - resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); - resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); - resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = (uint8_t) state; - resp.iString = 0; - - return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.h deleted file mode 100644 index fecf8596..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_device.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) - #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Must be called when the application is done with flashing started by -// tud_dfu_download_cb() and tud_dfu_manifest_cb(). -// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError -void tud_dfu_finish_flashing(uint8_t status); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. - -// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) -// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. -// During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); - -// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests -// This callback could be returned before flashing op is complete (async). -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); - -// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) -// Application can do checksum, or actual flashing if buffered entire image previously. -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt); - -// Invoked when received DFU_UPLOAD request -// Application must populate data with up to length bytes and -// Return the number of written bytes -TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_detach_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c deleted file mode 100644 index 7b77b3f8..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_DFU_RUNTIME) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_rt_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void) -{ -} - -void dfu_rtd_reset(uint8_t rhport) -{ - (void) rhport; -} - -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Runtime - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - TU_LOG2(" DFU RT Request: DETACH\r\n"); - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - } - break; - - case DFU_REQUEST_GETSTATUS: - { - TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_response_t resp; - // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - TU_VERIFY(tu_memset_s(&resp, sizeof(resp), 0x00, sizeof(resp))==0); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); - } - break; - - default: - { - TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); - return false; // stall unsupported request - } - } - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h deleted file mode 100644 index babaa821..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/dfu/dfu_rt_device.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid.h b/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid.h deleted file mode 100644 index fbd3eef3..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid.h +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_HID Human Interface Device (HID) - * @{ */ - -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ -/** \defgroup ClassDriver_HID_Common Common Definitions - * @{ */ - -/// USB HID Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ - uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ - - uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ - uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ - uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ - - uint8_t bReportType; /**< Type of HID class report. */ - uint16_t wReportLength; /**< the total size of the Report descriptor. */ -} tusb_hid_descriptor_hid_t; - -/// HID Subclass -typedef enum -{ - HID_SUBCLASS_NONE = 0, ///< No Subclass - HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_enum_t; - -/// HID Interface Protocol -typedef enum -{ - HID_ITF_PROTOCOL_NONE = 0, ///< None - HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_interface_protocol_enum_t; - -/// HID Descriptor Type -typedef enum -{ - HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor - HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor - HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_enum_t; - -/// HID Request Report Type -typedef enum -{ - HID_REPORT_TYPE_INVALID = 0, - HID_REPORT_TYPE_INPUT, ///< Input - HID_REPORT_TYPE_OUTPUT, ///< Output - HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; - -/// HID Class Specific Control Request -typedef enum -{ - HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report - HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle - HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol - HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report - HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle - HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_enum_t; - -/// HID Local Code -typedef enum -{ - HID_LOCAL_NotSupported = 0 , ///< NotSupported - HID_LOCAL_Arabic , ///< Arabic - HID_LOCAL_Belgian , ///< Belgian - HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual - HID_LOCAL_Canadian_French , ///< Canadian_French - HID_LOCAL_Czech_Republic , ///< Czech_Republic - HID_LOCAL_Danish , ///< Danish - HID_LOCAL_Finnish , ///< Finnish - HID_LOCAL_French , ///< French - HID_LOCAL_German , ///< German - HID_LOCAL_Greek , ///< Greek - HID_LOCAL_Hebrew , ///< Hebrew - HID_LOCAL_Hungary , ///< Hungary - HID_LOCAL_International , ///< International - HID_LOCAL_Italian , ///< Italian - HID_LOCAL_Japan_Katakana , ///< Japan_Katakana - HID_LOCAL_Korean , ///< Korean - HID_LOCAL_Latin_American , ///< Latin_American - HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch - HID_LOCAL_Norwegian , ///< Norwegian - HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) - HID_LOCAL_Poland , ///< Poland - HID_LOCAL_Portuguese , ///< Portuguese - HID_LOCAL_Russia , ///< Russia - HID_LOCAL_Slovakia , ///< Slovakia - HID_LOCAL_Spanish , ///< Spanish - HID_LOCAL_Swedish , ///< Swedish - HID_LOCAL_Swiss_French , ///< Swiss/French - HID_LOCAL_Swiss_German , ///< Swiss/German - HID_LOCAL_Switzerland , ///< Switzerland - HID_LOCAL_Taiwan , ///< Taiwan - HID_LOCAL_Turkish_Q , ///< Turkish-Q - HID_LOCAL_UK , ///< UK - HID_LOCAL_US , ///< US - HID_LOCAL_Yugoslavia , ///< Yugoslavia - HID_LOCAL_Turkish_F ///< Turkish-F -} hid_local_enum_t; - -// HID protocol value used by GetProtocol / SetProtocol -typedef enum -{ - HID_PROTOCOL_BOOT = 0, - HID_PROTOCOL_REPORT = 1 -} hid_protocol_mode_enum_t; - -/** @} */ - -//--------------------------------------------------------------------+ -// GAMEPAD -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Gamepad Gamepad - * @{ */ - -/* From https://www.kernel.org/doc/html/latest/input/gamepad.html - ____________________________ __ - / [__ZL__] [__ZR__] \ | - / [__ TL __] [__ TR __] \ | Front Triggers - __/________________________________\__ __| - / _ \ | - / /\ __ (N) \ | - / || __ |MO| __ _ _ \ | Main Pad - | <===DP===> |SE| |ST| (W) -|- (E) | | - \ || ___ ___ _ / | - /\ \/ / \ / \ (S) /\ __| - / \________ | LS | ____ | RS | ________/ \ | -| / \ \___/ / \ \___/ / \ | | Control Sticks -| / \_____/ \_____/ \ | __| -| / \ | - \_____/ \_____/ - - |________|______| |______|___________| - D-Pad Left Right Action Pad - Stick Stick - - |_____________| - Menu Pad - - Most gamepads have the following features: - - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. - - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. - - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. - - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also - provide a digital button if you press them. - - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons - are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. - - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. - */ - -/// HID Gamepad Protocol Report. -typedef struct TU_ATTR_PACKED -{ - int8_t x; ///< Delta x movement of left analog-stick - int8_t y; ///< Delta y movement of left analog-stick - int8_t z; ///< Delta z movement of right analog-joystick - int8_t rz; ///< Delta Rz movement of right analog-joystick - int8_t rx; ///< Delta Rx movement of analog left trigger - int8_t ry; ///< Delta Ry movement of analog right trigger - uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint32_t buttons; ///< Buttons mask for currently pressed buttons -}hid_gamepad_report_t; - -/// Standard Gamepad Buttons Bitmap -typedef enum -{ - GAMEPAD_BUTTON_0 = TU_BIT(0), - GAMEPAD_BUTTON_1 = TU_BIT(1), - GAMEPAD_BUTTON_2 = TU_BIT(2), - GAMEPAD_BUTTON_3 = TU_BIT(3), - GAMEPAD_BUTTON_4 = TU_BIT(4), - GAMEPAD_BUTTON_5 = TU_BIT(5), - GAMEPAD_BUTTON_6 = TU_BIT(6), - GAMEPAD_BUTTON_7 = TU_BIT(7), - GAMEPAD_BUTTON_8 = TU_BIT(8), - GAMEPAD_BUTTON_9 = TU_BIT(9), - GAMEPAD_BUTTON_10 = TU_BIT(10), - GAMEPAD_BUTTON_11 = TU_BIT(11), - GAMEPAD_BUTTON_12 = TU_BIT(12), - GAMEPAD_BUTTON_13 = TU_BIT(13), - GAMEPAD_BUTTON_14 = TU_BIT(14), - GAMEPAD_BUTTON_15 = TU_BIT(15), - GAMEPAD_BUTTON_16 = TU_BIT(16), - GAMEPAD_BUTTON_17 = TU_BIT(17), - GAMEPAD_BUTTON_18 = TU_BIT(18), - GAMEPAD_BUTTON_19 = TU_BIT(19), - GAMEPAD_BUTTON_20 = TU_BIT(20), - GAMEPAD_BUTTON_21 = TU_BIT(21), - GAMEPAD_BUTTON_22 = TU_BIT(22), - GAMEPAD_BUTTON_23 = TU_BIT(23), - GAMEPAD_BUTTON_24 = TU_BIT(24), - GAMEPAD_BUTTON_25 = TU_BIT(25), - GAMEPAD_BUTTON_26 = TU_BIT(26), - GAMEPAD_BUTTON_27 = TU_BIT(27), - GAMEPAD_BUTTON_28 = TU_BIT(28), - GAMEPAD_BUTTON_29 = TU_BIT(29), - GAMEPAD_BUTTON_30 = TU_BIT(30), - GAMEPAD_BUTTON_31 = TU_BIT(31), -}hid_gamepad_button_bm_t; - -/// Standard Gamepad Buttons Naming from Linux input event codes -/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h -#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 -#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 - -#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 -#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 - -#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 - -#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 -#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 - -#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 -#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 - -#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 -#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 -#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 -#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 -#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 -#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 -#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 -#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 -#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 -#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 - -/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -typedef enum -{ - GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED - GAMEPAD_HAT_UP = 1, ///< DPAD_UP - GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT - GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT - GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT - GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN - GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT - GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT - GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_t; - -/// @} - -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ - -/// Standard HID Boot Protocol Mouse Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ - int8_t x; /**< Current delta x movement of the mouse. */ - int8_t y; /**< Current delta y movement on the mouse. */ - int8_t wheel; /**< Current delta wheel movement on the mouse. */ - int8_t pan; // using AC Pan -} hid_mouse_report_t; - -/// Standard Mouse Buttons Bitmap -typedef enum -{ - MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button - MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button - MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button - MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, - MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, -}hid_mouse_button_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// Keyboard -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/// Standard HID Boot Protocol Keyboard Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ - uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ - uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ -} hid_keyboard_report_t; - -/// Keyboard modifier codes bitmap -typedef enum -{ - KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control - KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift - KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt - KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window - KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control - KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift - KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt - KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window -}hid_keyboard_modifier_bm_t; - -typedef enum -{ - KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED - KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED - KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED - KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode - KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode -}hid_keyboard_led_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// HID KEYCODE -//--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_ENTER 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_F16 0x6B -#define HID_KEY_F17 0x6C -#define HID_KEY_F18 0x6D -#define HID_KEY_F19 0x6E -#define HID_KEY_F20 0x6F -#define HID_KEY_F21 0x70 -#define HID_KEY_F22 0x71 -#define HID_KEY_F23 0x72 -#define HID_KEY_F24 0x73 -#define HID_KEY_EXECUTE 0x74 -#define HID_KEY_HELP 0x75 -#define HID_KEY_MENU 0x76 -#define HID_KEY_SELECT 0x77 -#define HID_KEY_STOP 0x78 -#define HID_KEY_AGAIN 0x79 -#define HID_KEY_UNDO 0x7A -#define HID_KEY_CUT 0x7B -#define HID_KEY_COPY 0x7C -#define HID_KEY_PASTE 0x7D -#define HID_KEY_FIND 0x7E -#define HID_KEY_MUTE 0x7F -#define HID_KEY_VOLUME_UP 0x80 -#define HID_KEY_VOLUME_DOWN 0x81 -#define HID_KEY_LOCKING_CAPS_LOCK 0x82 -#define HID_KEY_LOCKING_NUM_LOCK 0x83 -#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEY_KEYPAD_COMMA 0x85 -#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEY_KANJI1 0x87 -#define HID_KEY_KANJI2 0x88 -#define HID_KEY_KANJI3 0x89 -#define HID_KEY_KANJI4 0x8A -#define HID_KEY_KANJI5 0x8B -#define HID_KEY_KANJI6 0x8C -#define HID_KEY_KANJI7 0x8D -#define HID_KEY_KANJI8 0x8E -#define HID_KEY_KANJI9 0x8F -#define HID_KEY_LANG1 0x90 -#define HID_KEY_LANG2 0x91 -#define HID_KEY_LANG3 0x92 -#define HID_KEY_LANG4 0x93 -#define HID_KEY_LANG5 0x94 -#define HID_KEY_LANG6 0x95 -#define HID_KEY_LANG7 0x96 -#define HID_KEY_LANG8 0x97 -#define HID_KEY_LANG9 0x98 -#define HID_KEY_ALTERNATE_ERASE 0x99 -#define HID_KEY_SYSREQ_ATTENTION 0x9A -#define HID_KEY_CANCEL 0x9B -#define HID_KEY_CLEAR 0x9C -#define HID_KEY_PRIOR 0x9D -#define HID_KEY_RETURN 0x9E -#define HID_KEY_SEPARATOR 0x9F -#define HID_KEY_OUT 0xA0 -#define HID_KEY_OPER 0xA1 -#define HID_KEY_CLEAR_AGAIN 0xA2 -#define HID_KEY_CRSEL_PROPS 0xA3 -#define HID_KEY_EXSEL 0xA4 -// RESERVED 0xA5-DF -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 - - -//--------------------------------------------------------------------+ -// REPORT DESCRIPTOR -//--------------------------------------------------------------------+ - -//------------- ITEM & TAG -------------// -#define HID_REPORT_DATA_0(data) -#define HID_REPORT_DATA_1(data) , data -#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) -#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) - -#define HID_REPORT_ITEM(data, tag, type, size) \ - (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) - -// Report Item Types -enum { - RI_TYPE_MAIN = 0, - RI_TYPE_GLOBAL = 1, - RI_TYPE_LOCAL = 2 -}; - -//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// - -// Report Item Main group -enum { - RI_MAIN_INPUT = 8, - RI_MAIN_OUTPUT = 9, - RI_MAIN_COLLECTION = 10, - RI_MAIN_FEATURE = 11, - RI_MAIN_COLLECTION_END = 12 -}; - -#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) - -//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// -#define HID_DATA (0<<0) -#define HID_CONSTANT (1<<0) - -#define HID_ARRAY (0<<1) -#define HID_VARIABLE (1<<1) - -#define HID_ABSOLUTE (0<<2) -#define HID_RELATIVE (1<<2) - -#define HID_WRAP_NO (0<<3) -#define HID_WRAP (1<<3) - -#define HID_LINEAR (0<<4) -#define HID_NONLINEAR (1<<4) - -#define HID_PREFERRED_STATE (0<<5) -#define HID_PREFERRED_NO (1<<5) - -#define HID_NO_NULL_POSITION (0<<6) -#define HID_NULL_STATE (1<<6) - -#define HID_NON_VOLATILE (0<<7) -#define HID_VOLATILE (1<<7) - -#define HID_BITFIELD (0<<8) -#define HID_BUFFERED_BYTES (1<<8) - -//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// -enum { - HID_COLLECTION_PHYSICAL = 0, - HID_COLLECTION_APPLICATION, - HID_COLLECTION_LOGICAL, - HID_COLLECTION_REPORT, - HID_COLLECTION_NAMED_ARRAY, - HID_COLLECTION_USAGE_SWITCH, - HID_COLLECTION_USAGE_MODIFIER -}; - -//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// - -// Report Item Global group -enum { - RI_GLOBAL_USAGE_PAGE = 0, - RI_GLOBAL_LOGICAL_MIN = 1, - RI_GLOBAL_LOGICAL_MAX = 2, - RI_GLOBAL_PHYSICAL_MIN = 3, - RI_GLOBAL_PHYSICAL_MAX = 4, - RI_GLOBAL_UNIT_EXPONENT = 5, - RI_GLOBAL_UNIT = 6, - RI_GLOBAL_REPORT_SIZE = 7, - RI_GLOBAL_REPORT_ID = 8, - RI_GLOBAL_REPORT_COUNT = 9, - RI_GLOBAL_PUSH = 10, - RI_GLOBAL_POP = 11 -}; - -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) - -#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), - -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) - -#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) - -//------------- LOCAL ITEMS 6.2.2.8 -------------// - -enum { - RI_LOCAL_USAGE = 0, - RI_LOCAL_USAGE_MIN = 1, - RI_LOCAL_USAGE_MAX = 2, - RI_LOCAL_DESIGNATOR_INDEX = 3, - RI_LOCAL_DESIGNATOR_MIN = 4, - RI_LOCAL_DESIGNATOR_MAX = 5, - // 6 is reserved - RI_LOCAL_STRING_INDEX = 7, - RI_LOCAL_STRING_MIN = 8, - RI_LOCAL_STRING_MAX = 9, - RI_LOCAL_DELIMITER = 10, -}; - -#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) - -//--------------------------------------------------------------------+ -// Usage Table -//--------------------------------------------------------------------+ - -/// HID Usage Table - Table 1: Usage Page Summary -enum { - HID_USAGE_PAGE_DESKTOP = 0x01, - HID_USAGE_PAGE_SIMULATE = 0x02, - HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, - HID_USAGE_PAGE_SPORT = 0x04, - HID_USAGE_PAGE_GAME = 0x05, - HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, - HID_USAGE_PAGE_KEYBOARD = 0x07, - HID_USAGE_PAGE_LED = 0x08, - HID_USAGE_PAGE_BUTTON = 0x09, - HID_USAGE_PAGE_ORDINAL = 0x0a, - HID_USAGE_PAGE_TELEPHONY = 0x0b, - HID_USAGE_PAGE_CONSUMER = 0x0c, - HID_USAGE_PAGE_DIGITIZER = 0x0d, - HID_USAGE_PAGE_PID = 0x0f, - HID_USAGE_PAGE_UNICODE = 0x10, - HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, - HID_USAGE_PAGE_MEDICAL = 0x40, - HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 - HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 - HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, - HID_USAGE_PAGE_SCALE = 0x8d, - HID_USAGE_PAGE_MSR = 0x8e, - HID_USAGE_PAGE_CAMERA = 0x90, - HID_USAGE_PAGE_ARCADE = 0x91, - HID_USAGE_PAGE_FIDO = 0xF1D0, // FIDO alliance HID usage page - HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF -}; - -/// HID Usage Table - Table 6: Generic Desktop Page -enum { - HID_USAGE_DESKTOP_POINTER = 0x01, - HID_USAGE_DESKTOP_MOUSE = 0x02, - HID_USAGE_DESKTOP_JOYSTICK = 0x04, - HID_USAGE_DESKTOP_GAMEPAD = 0x05, - HID_USAGE_DESKTOP_KEYBOARD = 0x06, - HID_USAGE_DESKTOP_KEYPAD = 0x07, - HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, - HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, - HID_USAGE_DESKTOP_X = 0x30, - HID_USAGE_DESKTOP_Y = 0x31, - HID_USAGE_DESKTOP_Z = 0x32, - HID_USAGE_DESKTOP_RX = 0x33, - HID_USAGE_DESKTOP_RY = 0x34, - HID_USAGE_DESKTOP_RZ = 0x35, - HID_USAGE_DESKTOP_SLIDER = 0x36, - HID_USAGE_DESKTOP_DIAL = 0x37, - HID_USAGE_DESKTOP_WHEEL = 0x38, - HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, - HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, - HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, - HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, - HID_USAGE_DESKTOP_START = 0x3d, - HID_USAGE_DESKTOP_SELECT = 0x3e, - HID_USAGE_DESKTOP_VX = 0x40, - HID_USAGE_DESKTOP_VY = 0x41, - HID_USAGE_DESKTOP_VZ = 0x42, - HID_USAGE_DESKTOP_VBRX = 0x43, - HID_USAGE_DESKTOP_VBRY = 0x44, - HID_USAGE_DESKTOP_VBRZ = 0x45, - HID_USAGE_DESKTOP_VNO = 0x46, - HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, - HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, - HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, - HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, - HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, - HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, - HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, - HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, - HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, - HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, - HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, - HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, - HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, - HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, - HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, - HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, - HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, - HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, - HID_USAGE_DESKTOP_DPAD_UP = 0x90, - HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, - HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, - HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, - HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, - HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, - HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, - HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, - HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, - HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, - HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, - HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, - HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 -}; - - -/// HID Usage Table: Consumer Page (0x0C) -/// Only contains controls that supported by Windows (whole list is too long) -enum -{ - // Generic Control - HID_USAGE_CONSUMER_CONTROL = 0x0001, - - // Power Control - HID_USAGE_CONSUMER_POWER = 0x0030, - HID_USAGE_CONSUMER_RESET = 0x0031, - HID_USAGE_CONSUMER_SLEEP = 0x0032, - - // Screen Brightness - HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, - HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, - - // These HID usages operate only on mobile systems (battery powered) and - // require Windows 8 (build 8302 or greater). - HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, - HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, - HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, - HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, - - // Media Control - HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, - HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, - HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, - HID_USAGE_CONSUMER_STOP = 0x00B7, - HID_USAGE_CONSUMER_VOLUME = 0x00E0, - HID_USAGE_CONSUMER_MUTE = 0x00E2, - HID_USAGE_CONSUMER_BASS = 0x00E3, - HID_USAGE_CONSUMER_TREBLE = 0x00E4, - HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, - HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, - HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, - HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, - HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, - HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, - HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, - - // Application Launcher - HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, - HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, - HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, - HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, - - // Browser/Explorer Specific - HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, - HID_USAGE_CONSUMER_AC_HOME = 0x0223, - HID_USAGE_CONSUMER_AC_BACK = 0x0224, - HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, - HID_USAGE_CONSUMER_AC_STOP = 0x0226, - HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, - HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, - - // Mouse Horizontal scroll - HID_USAGE_CONSUMER_AC_PAN = 0x0238, -}; - -/// HID Usage Table: FIDO Alliance Page (0xF1D0) -enum -{ - HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection - HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report - HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report -}; - -/*-------------------------------------------------------------------- - * ASCII to KEYCODE Conversion - * Expand to array of [128][2] (shift, keycode) - * - * Usage: example to convert input chr into keyboard report (modifier + keycode) - * - * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; - * - * uint8_t keycode[6] = { 0 }; - * uint8_t modifier = 0; - * - * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; - * keycode[0] = conv_table[chr][1]; - * tud_hid_keyboard_report(report_id, modifier, keycode); - * - *--------------------------------------------------------------------*/ -#define HID_ASCII_TO_KEYCODE \ - {0, 0 }, /* 0x00 Null */ \ - {0, 0 }, /* 0x01 */ \ - {0, 0 }, /* 0x02 */ \ - {0, 0 }, /* 0x03 */ \ - {0, 0 }, /* 0x04 */ \ - {0, 0 }, /* 0x05 */ \ - {0, 0 }, /* 0x06 */ \ - {0, 0 }, /* 0x07 */ \ - {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ - {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ - {0, 0 }, /* 0x0B */ \ - {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_ENTER }, /* 0x0D CR */ \ - {0, 0 }, /* 0x0E */ \ - {0, 0 }, /* 0x0F */ \ - {0, 0 }, /* 0x10 */ \ - {0, 0 }, /* 0x11 */ \ - {0, 0 }, /* 0x12 */ \ - {0, 0 }, /* 0x13 */ \ - {0, 0 }, /* 0x14 */ \ - {0, 0 }, /* 0x15 */ \ - {0, 0 }, /* 0x16 */ \ - {0, 0 }, /* 0x17 */ \ - {0, 0 }, /* 0x18 */ \ - {0, 0 }, /* 0x19 */ \ - {0, 0 }, /* 0x1A */ \ - {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ - {0, 0 }, /* 0x1C */ \ - {0, 0 }, /* 0x1D */ \ - {0, 0 }, /* 0x1E */ \ - {0, 0 }, /* 0x1F */ \ - \ - {0, HID_KEY_SPACE }, /* 0x20 */ \ - {1, HID_KEY_1 }, /* 0x21 ! */ \ - {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ - {1, HID_KEY_3 }, /* 0x23 # */ \ - {1, HID_KEY_4 }, /* 0x24 $ */ \ - {1, HID_KEY_5 }, /* 0x25 % */ \ - {1, HID_KEY_7 }, /* 0x26 & */ \ - {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ - {1, HID_KEY_9 }, /* 0x28 ( */ \ - {1, HID_KEY_0 }, /* 0x29 ) */ \ - {1, HID_KEY_8 }, /* 0x2A * */ \ - {1, HID_KEY_EQUAL }, /* 0x2B + */ \ - {0, HID_KEY_COMMA }, /* 0x2C , */ \ - {0, HID_KEY_MINUS }, /* 0x2D - */ \ - {0, HID_KEY_PERIOD }, /* 0x2E . */ \ - {0, HID_KEY_SLASH }, /* 0x2F / */ \ - {0, HID_KEY_0 }, /* 0x30 0 */ \ - {0, HID_KEY_1 }, /* 0x31 1 */ \ - {0, HID_KEY_2 }, /* 0x32 2 */ \ - {0, HID_KEY_3 }, /* 0x33 3 */ \ - {0, HID_KEY_4 }, /* 0x34 4 */ \ - {0, HID_KEY_5 }, /* 0x35 5 */ \ - {0, HID_KEY_6 }, /* 0x36 6 */ \ - {0, HID_KEY_7 }, /* 0x37 7 */ \ - {0, HID_KEY_8 }, /* 0x38 8 */ \ - {0, HID_KEY_9 }, /* 0x39 9 */ \ - {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ - {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ - {1, HID_KEY_COMMA }, /* 0x3C < */ \ - {0, HID_KEY_EQUAL }, /* 0x3D = */ \ - {1, HID_KEY_PERIOD }, /* 0x3E > */ \ - {1, HID_KEY_SLASH }, /* 0x3F ? */ \ - \ - {1, HID_KEY_2 }, /* 0x40 @ */ \ - {1, HID_KEY_A }, /* 0x41 A */ \ - {1, HID_KEY_B }, /* 0x42 B */ \ - {1, HID_KEY_C }, /* 0x43 C */ \ - {1, HID_KEY_D }, /* 0x44 D */ \ - {1, HID_KEY_E }, /* 0x45 E */ \ - {1, HID_KEY_F }, /* 0x46 F */ \ - {1, HID_KEY_G }, /* 0x47 G */ \ - {1, HID_KEY_H }, /* 0x48 H */ \ - {1, HID_KEY_I }, /* 0x49 I */ \ - {1, HID_KEY_J }, /* 0x4A J */ \ - {1, HID_KEY_K }, /* 0x4B K */ \ - {1, HID_KEY_L }, /* 0x4C L */ \ - {1, HID_KEY_M }, /* 0x4D M */ \ - {1, HID_KEY_N }, /* 0x4E N */ \ - {1, HID_KEY_O }, /* 0x4F O */ \ - {1, HID_KEY_P }, /* 0x50 P */ \ - {1, HID_KEY_Q }, /* 0x51 Q */ \ - {1, HID_KEY_R }, /* 0x52 R */ \ - {1, HID_KEY_S }, /* 0x53 S */ \ - {1, HID_KEY_T }, /* 0x55 T */ \ - {1, HID_KEY_U }, /* 0x55 U */ \ - {1, HID_KEY_V }, /* 0x56 V */ \ - {1, HID_KEY_W }, /* 0x57 W */ \ - {1, HID_KEY_X }, /* 0x58 X */ \ - {1, HID_KEY_Y }, /* 0x59 Y */ \ - {1, HID_KEY_Z }, /* 0x5A Z */ \ - {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ - {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ - {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ - {1, HID_KEY_6 }, /* 0x5E ^ */ \ - {1, HID_KEY_MINUS }, /* 0x5F _ */ \ - \ - {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ - {0, HID_KEY_A }, /* 0x61 a */ \ - {0, HID_KEY_B }, /* 0x62 b */ \ - {0, HID_KEY_C }, /* 0x63 c */ \ - {0, HID_KEY_D }, /* 0x66 d */ \ - {0, HID_KEY_E }, /* 0x65 e */ \ - {0, HID_KEY_F }, /* 0x66 f */ \ - {0, HID_KEY_G }, /* 0x67 g */ \ - {0, HID_KEY_H }, /* 0x68 h */ \ - {0, HID_KEY_I }, /* 0x69 i */ \ - {0, HID_KEY_J }, /* 0x6A j */ \ - {0, HID_KEY_K }, /* 0x6B k */ \ - {0, HID_KEY_L }, /* 0x6C l */ \ - {0, HID_KEY_M }, /* 0x6D m */ \ - {0, HID_KEY_N }, /* 0x6E n */ \ - {0, HID_KEY_O }, /* 0x6F o */ \ - {0, HID_KEY_P }, /* 0x70 p */ \ - {0, HID_KEY_Q }, /* 0x71 q */ \ - {0, HID_KEY_R }, /* 0x72 r */ \ - {0, HID_KEY_S }, /* 0x73 s */ \ - {0, HID_KEY_T }, /* 0x75 t */ \ - {0, HID_KEY_U }, /* 0x75 u */ \ - {0, HID_KEY_V }, /* 0x76 v */ \ - {0, HID_KEY_W }, /* 0x77 w */ \ - {0, HID_KEY_X }, /* 0x78 x */ \ - {0, HID_KEY_Y }, /* 0x79 y */ \ - {0, HID_KEY_Z }, /* 0x7A z */ \ - {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ - {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ - {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ - {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ - {0, HID_KEY_DELETE } /* 0x7F Delete */ \ - -/*-------------------------------------------------------------------- - * KEYCODE to Ascii Conversion - * Expand to array of [128][2] (ascii without shift, ascii with shift) - * - * Usage: example to convert ascii from keycode (key) and shift modifier (shift). - * Here we assume key < 128 ( printable ) - * - * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; - * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; - * - *--------------------------------------------------------------------*/ -#define HID_KEYCODE_TO_ASCII \ - {0 , 0 }, /* 0x00 */ \ - {0 , 0 }, /* 0x01 */ \ - {0 , 0 }, /* 0x02 */ \ - {0 , 0 }, /* 0x03 */ \ - {'a' , 'A' }, /* 0x04 */ \ - {'b' , 'B' }, /* 0x05 */ \ - {'c' , 'C' }, /* 0x06 */ \ - {'d' , 'D' }, /* 0x07 */ \ - {'e' , 'E' }, /* 0x08 */ \ - {'f' , 'F' }, /* 0x09 */ \ - {'g' , 'G' }, /* 0x0a */ \ - {'h' , 'H' }, /* 0x0b */ \ - {'i' , 'I' }, /* 0x0c */ \ - {'j' , 'J' }, /* 0x0d */ \ - {'k' , 'K' }, /* 0x0e */ \ - {'l' , 'L' }, /* 0x0f */ \ - {'m' , 'M' }, /* 0x10 */ \ - {'n' , 'N' }, /* 0x11 */ \ - {'o' , 'O' }, /* 0x12 */ \ - {'p' , 'P' }, /* 0x13 */ \ - {'q' , 'Q' }, /* 0x14 */ \ - {'r' , 'R' }, /* 0x15 */ \ - {'s' , 'S' }, /* 0x16 */ \ - {'t' , 'T' }, /* 0x17 */ \ - {'u' , 'U' }, /* 0x18 */ \ - {'v' , 'V' }, /* 0x19 */ \ - {'w' , 'W' }, /* 0x1a */ \ - {'x' , 'X' }, /* 0x1b */ \ - {'y' , 'Y' }, /* 0x1c */ \ - {'z' , 'Z' }, /* 0x1d */ \ - {'1' , '!' }, /* 0x1e */ \ - {'2' , '@' }, /* 0x1f */ \ - {'3' , '#' }, /* 0x20 */ \ - {'4' , '$' }, /* 0x21 */ \ - {'5' , '%' }, /* 0x22 */ \ - {'6' , '^' }, /* 0x23 */ \ - {'7' , '&' }, /* 0x24 */ \ - {'8' , '*' }, /* 0x25 */ \ - {'9' , '(' }, /* 0x26 */ \ - {'0' , ')' }, /* 0x27 */ \ - {'\r' , '\r' }, /* 0x28 */ \ - {'\x1b', '\x1b' }, /* 0x29 */ \ - {'\b' , '\b' }, /* 0x2a */ \ - {'\t' , '\t' }, /* 0x2b */ \ - {' ' , ' ' }, /* 0x2c */ \ - {'-' , '_' }, /* 0x2d */ \ - {'=' , '+' }, /* 0x2e */ \ - {'[' , '{' }, /* 0x2f */ \ - {']' , '}' }, /* 0x30 */ \ - {'\\' , '|' }, /* 0x31 */ \ - {'#' , '~' }, /* 0x32 */ \ - {';' , ':' }, /* 0x33 */ \ - {'\'' , '\"' }, /* 0x34 */ \ - {'`' , '~' }, /* 0x35 */ \ - {',' , '<' }, /* 0x36 */ \ - {'.' , '>' }, /* 0x37 */ \ - {'/' , '?' }, /* 0x38 */ \ - \ - {0 , 0 }, /* 0x39 */ \ - {0 , 0 }, /* 0x3a */ \ - {0 , 0 }, /* 0x3b */ \ - {0 , 0 }, /* 0x3c */ \ - {0 , 0 }, /* 0x3d */ \ - {0 , 0 }, /* 0x3e */ \ - {0 , 0 }, /* 0x3f */ \ - {0 , 0 }, /* 0x40 */ \ - {0 , 0 }, /* 0x41 */ \ - {0 , 0 }, /* 0x42 */ \ - {0 , 0 }, /* 0x43 */ \ - {0 , 0 }, /* 0x44 */ \ - {0 , 0 }, /* 0x45 */ \ - {0 , 0 }, /* 0x46 */ \ - {0 , 0 }, /* 0x47 */ \ - {0 , 0 }, /* 0x48 */ \ - {0 , 0 }, /* 0x49 */ \ - {0 , 0 }, /* 0x4a */ \ - {0 , 0 }, /* 0x4b */ \ - {0 , 0 }, /* 0x4c */ \ - {0 , 0 }, /* 0x4d */ \ - {0 , 0 }, /* 0x4e */ \ - {0 , 0 }, /* 0x4f */ \ - {0 , 0 }, /* 0x50 */ \ - {0 , 0 }, /* 0x51 */ \ - {0 , 0 }, /* 0x52 */ \ - {0 , 0 }, /* 0x53 */ \ - \ - {'/' , '/' }, /* 0x54 */ \ - {'*' , '*' }, /* 0x55 */ \ - {'-' , '-' }, /* 0x56 */ \ - {'+' , '+' }, /* 0x57 */ \ - {'\r' , '\r' }, /* 0x58 */ \ - {'1' , 0 }, /* 0x59 */ \ - {'2' , 0 }, /* 0x5a */ \ - {'3' , 0 }, /* 0x5b */ \ - {'4' , 0 }, /* 0x5c */ \ - {'5' , '5' }, /* 0x5d */ \ - {'6' , 0 }, /* 0x5e */ \ - {'7' , 0 }, /* 0x5f */ \ - {'8' , 0 }, /* 0x60 */ \ - {'9' , 0 }, /* 0x61 */ \ - {'0' , 0 }, /* 0x62 */ \ - {'.' , 0 }, /* 0x63 */ \ - {0 , 0 }, /* 0x64 */ \ - {0 , 0 }, /* 0x65 */ \ - {0 , 0 }, /* 0x66 */ \ - {'=' , '=' }, /* 0x67 */ \ - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_H__ */ - -/// @} diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.c deleted file mode 100644 index 9240fe2c..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_HID) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "hid_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t itf_protocol; // Boot mouse or keyboard - - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - uint8_t idle_rate; // up to application to handle idle rate - uint16_t report_desc_len; - - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; - - // TODO save hid descriptor since host can specifically request this after enumeration - // Note: HID descriptor may be not available from application after enumeration - tusb_hid_descriptor_hid_t const * hid_descriptor; -} hidd_interface_t; - -CFG_TUSB_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID]; - -/*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return i; - } - - return 0xFF; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t instance) -{ - uint8_t const rhport = 0; - uint8_t const ep_in = _hidd_itf[instance].ep_in; - return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in); -} - -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint16_t len) -{ - uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[instance]; - - // claim endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); - - // prepare data - if (report_id) - { - p_hid->epin_buf[0] = report_id; - TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf+1, CFG_TUD_HID_EP_BUFSIZE-1, report, len)); - len++; - }else - { - TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf, CFG_TUD_HID_EP_BUFSIZE, report, len)); - } - - return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len); -} - -uint8_t tud_hid_n_interface_protocol(uint8_t instance) -{ - return _hidd_itf[instance].itf_protocol; -} - -uint8_t tud_hid_n_get_protocol(uint8_t instance) -{ - return _hidd_itf[instance].protocol_mode; -} - -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - hid_keyboard_report_t report; - - report.modifier = modifier; - report.reserved = 0; - - if ( keycode ) - { - memcpy(report.keycode, keycode, sizeof(report.keycode)); - }else - { - tu_memclr(report.keycode, 6); - } - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, - uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - hid_mouse_report_t report = - { - .buttons = buttons, - .x = x, - .y = y, - .wheel = vertical, - .pan = horizontal - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { - hid_gamepad_report_t report = - { - .x = x, - .y = y, - .z = z, - .rz = rz, - .rx = rx, - .ry = ry, - .hat = hat, - .buttons = buttons, - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -//--------------------------------------------------------------------+ -// USBD-CLASS API -//--------------------------------------------------------------------+ -void hidd_init(void) -{ - hidd_reset(0); -} - -void hidd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(_hidd_itf, sizeof(_hidd_itf)); -} - -uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) - { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = - (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(max_len >= drv_len, 0); - - // Find available interface - hidd_interface_t * p_hid = NULL; - uint8_t hid_id; - for(hid_id=0; hid_idhid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - - p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Use offsetof to avoid pointer to the odd/misaligned address - p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); - - // Prepare for output endpoint - if (p_hid->ep_out) - { - if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) - { - TU_LOG_FAILED(); - TU_BREAKPOINT(); - } - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - //------------- STD Request -------------// - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const desc_type = tu_u16_high(request->wValue); - //uint8_t const desc_index = tu_u16_low (request->wValue); - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); - } - else - { - return false; // stall unsupported request - } - } - } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - //------------- Class Specific Request -------------// - switch( request->bRequest ) - { - case HID_REQ_CONTROL_GET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - uint16_t xferlen = 0; - - // If host request a specific Report ID, add ID to as 1 byte of response - if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) - { - *report_buf++ = report_id; - req_len--; - - xferlen++; - } - - xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); - TU_ASSERT( xferlen > 0 ); - - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } - break; - - case HID_REQ_CONTROL_SET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) - { - report_buf++; - report_len--; - } - - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); - } - break; - - case HID_REQ_CONTROL_SET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) - { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); - } - - tud_control_status(rhport, request); - } - break; - - case HID_REQ_CONTROL_GET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); - } - break; - - case HID_REQ_CONTROL_GET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); - } - break; - - case HID_REQ_CONTROL_SET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - p_hid->protocol_mode = (uint8_t) request->wValue; - if (tud_hid_set_protocol_cb) - { - tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); - } - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // stall unsupported request - } - - return true; -} - -bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t instance = 0; - hidd_interface_t * p_hid = _hidd_itf; - - // Identify which interface to use - for (instance = 0; instance < CFG_TUD_HID; instance++) - { - p_hid = &_hidd_itf[instance]; - if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; - } - TU_ASSERT(instance < CFG_TUD_HID); - - // Sent report successfully - if (ep_addr == p_hid->ep_in) - { - if (tud_hid_report_complete_cb) - { - tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes); - } - } - // Received report - else if (ep_addr == p_hid->ep_out) - { - tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, (uint16_t) xferred_bytes); - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); - } - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.h deleted file mode 100644 index 17b24def..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_device.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_DEVICE_H_ -#define _TUSB_HID_DEVICE_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE -#endif - -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUD_HID > 1 -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tud_hid_n_interface_protocol(uint8_t instance); - -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -uint8_t tud_hid_n_get_protocol(uint8_t instance); - -// Send report to host -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint16_t len); - -// KEYBOARD: convenient helper to send keyboard report if application -// use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); - -// MOUSE: convenient helper to send mouse report if application -// use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); - -// Gamepad: convenient helper to send gamepad report if application -// use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline uint8_t tud_hid_interface_protocol(void); -static inline uint8_t tud_hid_get_protocol(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET HID REPORT DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); - -// Invoked when received SET_PROTOCOL request -// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); - -// Invoked when received SET_IDLE request. return false will stall the request -// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len); - - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void) -{ - return tud_hid_n_ready(0); -} - -static inline uint8_t tud_hid_interface_protocol(void) -{ - return tud_hid_n_interface_protocol(0); -} - -static inline uint8_t tud_hid_get_protocol(void) -{ - return tud_hid_n_get_protocol(0); -} - -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) -{ - return tud_hid_n_report(0, report_id, report, len); -} - -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); -} - -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); -} - -/* --------------------------------------------------------------------+ - * HID Report Descriptor Template - * - * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave - * empty if multiple reports is not used - * - * - Only 1 report: no parameter - * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; - * - * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template - * uint8_t const report_desc[] = - * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) - * }; - *--------------------------------------------------------------------*/ - -// Keyboard Report Descriptor Template -#define TUD_HID_REPORT_DESC_KEYBOARD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bits Modifier Keys (Shift, Control, Alt) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 224 ) ,\ - HID_USAGE_MAX ( 231 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 8 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit reserved */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_REPORT_COUNT ( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* led padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_OUTPUT ( HID_CONSTANT ) ,\ - /* 6-byte Keycodes */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX_N ( 255, 2 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N( 255, 2 ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// Mouse Report Descriptor Template -#define TUD_HID_REPORT_DESC_MOUSE(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ - HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - /* Left, Right, Middle, Backward, Forward buttons */ \ - HID_REPORT_COUNT( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 3 bit padding */ \ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - /* X, Y position [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - /* Verital wheel scroll [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ - /* Horizontal wheel scroll [-127, 127] */ \ - HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ - HID_LOGICAL_MIN ( 0x81 ), \ - HID_LOGICAL_MAX ( 0x7f ), \ - HID_REPORT_COUNT( 1 ), \ - HID_REPORT_SIZE ( 8 ), \ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ - HID_COLLECTION_END , \ - HID_COLLECTION_END \ - -// Consumer Control Report Descriptor Template -#define TUD_HID_REPORT_DESC_CONSUMER(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\ - HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_LOGICAL_MIN ( 0x00 ) ,\ - HID_LOGICAL_MAX_N( 0x03FF, 2 ) ,\ - HID_USAGE_MIN ( 0x00 ) ,\ - HID_USAGE_MAX_N ( 0x03FF, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 16 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -/* System Control Report Descriptor Template - * 0x00 - do nothing - * 0x01 - Power Off - * 0x02 - Standby - * 0x03 - Wake Host - */ -#define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 2 bit system power control */ \ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 3 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - /* 6 bit padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 6 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_COLLECTION_END \ - -// Gamepad Report Descriptor Template -// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout -// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | -#define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit DPad/Hat Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 8 ) ,\ - HID_PHYSICAL_MIN ( 0 ) ,\ - HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 32 bit Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 32 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 32 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// FIDO U2F Authenticator Descriptor Template -// - 1st parameter is report size, which is 64 bytes maximum in U2F -// - 2nd parameter is HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_FIDO_U2F(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_FIDO, 2 ) ,\ - HID_USAGE ( HID_USAGE_FIDO_U2FHID ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */ \ - __VA_ARGS__ \ - /* Usage Data In */ \ - HID_USAGE ( HID_USAGE_FIDO_DATA_IN ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_REPORT_COUNT ( report_size ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* Usage Data Out */ \ - HID_USAGE ( HID_USAGE_FIDO_DATA_OUT ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_REPORT_COUNT ( report_size ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// HID Generic Input & Output -// - 1st parameter is report size (mandatory) -// - 2nd parameter is report id HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_GENERIC_INOUT(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ - HID_USAGE ( 0x01 ),\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* Input */ \ - HID_USAGE ( 0x02 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - /* Output */ \ - HID_USAGE ( 0x03 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - HID_COLLECTION_END \ - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.c b/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.c deleted file mode 100644 index d95d3ef3..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_HID) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "hid_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t daddr; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t itf_protocol; // None, Keyboard, Mouse - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - - uint8_t report_desc_type; - uint16_t report_desc_len; - - uint16_t epin_size; - uint16_t epout_size; - - CFG_TUH_MEM_ALIGN uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; - CFG_TUH_MEM_ALIGN uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; -} hidh_interface_t; - -CFG_TUH_MEM_SECTION -tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID]; - -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline -hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) -{ - TU_ASSERT(daddr && idx < CFG_TUH_HID, NULL); - hidh_interface_t* p_hid = &_hidh_itf[idx]; - return (p_hid->daddr == daddr) ? p_hid : NULL; -} - -// Get instance ID by endpoint address -static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && - (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr) ) - { - return idx; - } - } - - return TUSB_INDEX_INVALID_8; -} - -static hidh_interface_t* find_new_itf(void) -{ - for(uint8_t i=0; idaddr = daddr; - - // re-construct descriptor - tusb_desc_interface_t* desc = &info->desc; - desc->bLength = sizeof(tusb_desc_interface_t); - desc->bDescriptorType = TUSB_DESC_INTERFACE; - - desc->bInterfaceNumber = p_hid->itf_num; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u)); - desc->bInterfaceClass = TUSB_CLASS_HID; - desc->bInterfaceSubClass = (p_hid->itf_protocol ? HID_SUBCLASS_BOOT : HID_SUBCLASS_NONE); - desc->bInterfaceProtocol = p_hid->itf_protocol; - desc->iInterface = 0; // not used yet - - return true; -} - -uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx; - } - - return TUSB_INDEX_INVALID_8; -} - -uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - return p_hid ? p_hid->itf_protocol : 0; -} - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - return p_hid ? p_hid->protocol_mode : 0; -} - -static void set_protocol_complete(tuh_xfer_t* xfer) -{ - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - if (XFER_RESULT_SUCCESS == xfer->result) - { - p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue); - } - - if (tuh_hid_set_protocol_complete_cb) - { - tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode); - } -} - -static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - TU_LOG2("HID Set Protocol = %d\r\n", protocol); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = itf_num, - .wLength = 0 - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid && p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE); - - return _hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0); -} - -static void set_report_complete(tuh_xfer_t* xfer) -{ - TU_LOG2("HID Set Report complete\r\n"); - - if (tuh_hid_set_report_complete_cb) - { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); - - uint8_t const report_type = tu_u16_high(xfer->setup->wValue); - uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - - tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type, - (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); - } -} - -bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_htole16(tu_u16(report_type, report_id)), - .wIndex = tu_htole16((uint16_t)p_hid->itf_num), - .wLength = len - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = report, - .complete_cb = set_report_complete, - .user_data = 0 - }; - - return tuh_control_xfer(&xfer); -} - -static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = tu_htole16(idle_rate), - .wIndex = tu_htole16((uint16_t)itf_num), - .wLength = 0 - }; - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data - }; - - return tuh_control_xfer(&xfer); -} - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if HID interface is ready to receive report -bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); - TU_VERIFY(p_hid); - - return !usbh_edpt_busy(dev_addr, p_hid->ep_in); -} - -bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_in) ); - - if ( !usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size) ) - { - usbh_edpt_release(daddr, p_hid->ep_in); - return false; - } - - return true; -} - -bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) -{ - hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); - TU_VERIFY(p_hid); - - return !usbh_edpt_busy(dev_addr, p_hid->ep_out); -} - -bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) -{ - TU_LOG2("HID Send Report %d\r\n", report_id); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - if (p_hid->ep_out == 0) - { - // This HID does not have an out endpoint (other than control) - return false; - } - else if (len > CFG_TUH_HID_EPOUT_BUFSIZE || - (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1))) - { - // ep_out buffer is not large enough to hold contents - return false; - } - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_out) ); - - if (report_id == 0) - { - // No report ID in transmission - memcpy(&p_hid->epout_buf[0], report, len); - } - else - { - p_hid->epout_buf[0] = report_id; - memcpy(&p_hid->epout_buf[1], report, len); - ++len; // 1 more byte for report_id - } - - TU_LOG3_MEM(p_hid->epout_buf, len, 2); - - if ( !usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len) ) - { - usbh_edpt_release(daddr, p_hid->ep_out); - return false; - } - - return true; -} - -//--------------------------------------------------------------------+ -// USBH API -//--------------------------------------------------------------------+ -void hidh_init(void) -{ - tu_memclr(_hidh_itf, sizeof(_hidh_itf)); -} - -bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const idx = get_idx_by_epaddr(daddr, ep_addr); - - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid); - - if ( dir == TUSB_DIR_IN ) - { - TU_LOG2(" Get Report callback (%u, %u)\r\n", daddr, idx); - TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2); - tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes); - }else - { - if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes); - } - - return true; -} - -void hidh_close(uint8_t daddr) -{ - for(uint8_t i=0; idaddr == daddr) - { - if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); - p_hid->daddr = 0; - } - } -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ - -bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - - TU_LOG2("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(max_len >= drv_len); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - //------------- HID descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); - - hidh_interface_t* p_hid = find_new_itf(); - TU_ASSERT(p_hid); // not enough interface, try to increase CFG_TUH_HID - p_hid->daddr = daddr; - - //------------- Endpoint Descriptors -------------// - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - for(int i = 0; i < desc_itf->bNumEndpoints; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); - - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - p_hid->ep_in = desc_ep->bEndpointAddress; - p_hid->epin_size = tu_edpt_packet_size(desc_ep); - } - else - { - p_hid->ep_out = desc_ep->bEndpointAddress; - p_hid->epout_size = tu_edpt_packet_size(desc_ep); - } - - p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; - } - - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Assume bNumDescriptors = 1 - p_hid->report_desc_type = desc_hid->bReportType; - p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - - // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config - p_hid->protocol_mode = HID_PROTOCOL_BOOT; - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { - p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - } - - return true; -} - -//--------------------------------------------------------------------+ -// Set Configure -//--------------------------------------------------------------------+ - -enum { - CONFG_SET_IDLE, - CONFIG_SET_PROTOCOL, - CONFIG_GET_REPORT_DESC, - CONFIG_COMPLETE -}; - -static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len); -static void process_set_config(tuh_xfer_t* xfer); - -bool hidh_set_config(uint8_t daddr, uint8_t itf_num) -{ - tusb_control_request_t request; - request.wIndex = tu_htole16((uint16_t) itf_num); - - tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = CONFG_SET_IDLE; - - // fake request to kick-off the set config process - process_set_config(&xfer); - - return true; -} - -static void process_set_config(tuh_xfer_t* xfer) -{ - // Stall is a valid response for SET_IDLE, sometime SET_PROTOCOL as well - // therefore we could ignore its result - if ( !(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE || - xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL) ) - { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - } - - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; - - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - switch(state) - { - case CONFG_SET_IDLE: - { - // Idle rate = 0 mean only report when there is changes - const uint16_t idle_rate = 0; - const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; - _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state); - } - break; - - case CONFIG_SET_PROTOCOL: - _hidh_set_protocol(daddr, p_hid->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); - break; - - case CONFIG_GET_REPORT_DESC: - // Get Report Descriptor if possible - // using usbh enumeration buffer since report descriptor can be very long - if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) - { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); - - // Driver is mounted without report descriptor - config_driver_mount_complete(daddr, idx, NULL, 0); - }else - { - tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0, usbh_get_enum_buf(), p_hid->report_desc_len, process_set_config, CONFIG_COMPLETE); - } - break; - - case CONFIG_COMPLETE: - { - uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = tu_le16toh(xfer->setup->wLength); - - config_driver_mount_complete(daddr, idx, desc_report, desc_len); - } - break; - - default: break; - } -} - -static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len) -{ - hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); - - // enumeration is complete - if (tuh_hid_mount_cb) tuh_hid_mount_cb(daddr, idx, desc_report, desc_len); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(daddr, p_hid->itf_num); -} - -//--------------------------------------------------------------------+ -// Report Descriptor Parser -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) -{ - // Report Item 6.2.2.2 USB HID 1.11 - union TU_ATTR_PACKED - { - uint8_t byte; - struct TU_ATTR_PACKED - { - uint8_t size : 2; - uint8_t type : 2; - uint8_t tag : 4; - }; - } header; - - tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info_arr; - - // current parsed report count & size from descriptor -// uint8_t ri_report_count = 0; -// uint8_t ri_report_size = 0; - - uint8_t ri_collection_depth = 0; - - while(desc_len && report_num < arr_count) - { - header.byte = *desc_report++; - desc_len--; - - uint8_t const tag = header.tag; - uint8_t const type = header.type; - uint8_t const size = header.size; - - uint8_t const data8 = desc_report[0]; - - TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iusage_page, desc_report, size); - break; - - case RI_GLOBAL_LOGICAL_MIN : break; - case RI_GLOBAL_LOGICAL_MAX : break; - case RI_GLOBAL_PHYSICAL_MIN : break; - case RI_GLOBAL_PHYSICAL_MAX : break; - - case RI_GLOBAL_REPORT_ID: - info->report_id = data8; - break; - - case RI_GLOBAL_REPORT_SIZE: -// ri_report_size = data8; - break; - - case RI_GLOBAL_REPORT_COUNT: -// ri_report_count = data8; - break; - - case RI_GLOBAL_UNIT_EXPONENT : break; - case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_PUSH : break; - case RI_GLOBAL_POP : break; - - default: break; - } - break; - - case RI_TYPE_LOCAL: - switch(tag) - { - case RI_LOCAL_USAGE: - // only take in account the "usage" before starting REPORT ID - if ( ri_collection_depth == 0 ) info->usage = data8; - break; - - case RI_LOCAL_USAGE_MIN : break; - case RI_LOCAL_USAGE_MAX : break; - case RI_LOCAL_DESIGNATOR_INDEX : break; - case RI_LOCAL_DESIGNATOR_MIN : break; - case RI_LOCAL_DESIGNATOR_MAX : break; - case RI_LOCAL_STRING_INDEX : break; - case RI_LOCAL_STRING_MIN : break; - case RI_LOCAL_STRING_MAX : break; - case RI_LOCAL_DELIMITER : break; - default: break; - } - break; - - // error - default: break; - } - - desc_report += size; - desc_len -= size; - } - - for ( uint8_t i = 0; i < report_num; i++ ) - { - info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); - } - - return report_num; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.h b/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.h deleted file mode 100644 index 08ad421d..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/hid/hid_host.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// TODO Highspeed interrupt can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#endif - -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 -#endif - - -typedef struct -{ - uint8_t report_id; - uint8_t usage; - uint16_t usage_page; - - // TODO still use the endpoint size for now -// uint8_t in_len; // length of IN report -// uint8_t out_len; // length of OUT report -} tuh_hid_report_info_t; - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -// Get the total number of mounted HID interfaces of a device -uint8_t tuh_hid_itf_get_count(uint8_t dev_addr); - -// Get all mounted interfaces across devices -uint8_t tuh_hid_itf_get_total_count(void); - -// backward compatible rename -#define tuh_hid_instance_count tuh_hid_itf_get_count - -// Get Interface information -bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* itf_info); - -// Get Interface index from device address + interface number -// return TUSB_INDEX_INVALID_8 (0xFF) if not found -uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t idx); - -// Check if HID interface is mounted -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t idx); - -// Parse report descriptor into array of report_info struct and return number of reports. -// For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: Device will be initialized in Boot protocol for simplicity. -// Application can use set_protocol() to switch back to Report protocol. -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t idx); - -// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t idx, uint8_t protocol); - -// Set Report using control endpoint -// report_type is either Input, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if HID interface is ready to receive report -bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx); - -// Try to receive next report on Interrupt Endpoint. Immediately return -// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available -// - false if failed to queue the transfer e.g endpoint is busy -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t idx); - -// Check if HID interface is ready to send report -bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx); - -// Send report using interrupt endpoint -// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. -bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -TU_ATTR_WEAK void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len); - -// Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx); - -// Invoked when received report from device via interrupt endpoint -// Note: if there is report ID (composite), it is 1st byte of report -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); - -// Invoked when sent report to device successfully via interrupt endpoint -TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); - -// Invoked when Sent Report to device via either control endpoint -// len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); - -// Invoked when Set Protocol request is complete -TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidh_init (void); -bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_HID_HOST_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi.h b/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi.h deleted file mode 100644 index 8ddcdfda..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_MIDI_H__ -#define _TUSB_MIDI_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Specific Descriptor -//--------------------------------------------------------------------+ - -typedef enum -{ - MIDI_CS_INTERFACE_HEADER = 0x01, - MIDI_CS_INTERFACE_IN_JACK = 0x02, - MIDI_CS_INTERFACE_OUT_JACK = 0x03, - MIDI_CS_INTERFACE_ELEMENT = 0x04, -} midi_cs_interface_subtype_t; - -typedef enum -{ - MIDI_CS_ENDPOINT_GENERAL = 0x01 -} midi_cs_endpoint_subtype_t; - -typedef enum -{ - MIDI_JACK_EMBEDDED = 0x01, - MIDI_JACK_EXTERNAL = 0x02 -} midi_jack_type_t; - -typedef enum -{ - MIDI_CIN_MISC = 0, - MIDI_CIN_CABLE_EVENT = 1, - MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect - MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP - MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue - MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message - MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data - MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data - MIDI_CIN_NOTE_OFF = 8, - MIDI_CIN_NOTE_ON = 9, - MIDI_CIN_POLY_KEYPRESS = 10, - MIDI_CIN_CONTROL_CHANGE = 11, - MIDI_CIN_PROGRAM_CHANGE = 12, - MIDI_CIN_CHANNEL_PRESSURE = 13, - MIDI_CIN_PITCH_BEND_CHANGE = 14, - MIDI_CIN_1BYTE_DATA = 15 -} midi_code_index_number_t; - -// MIDI 1.0 status byte -enum -{ - //------------- System Exclusive -------------// - MIDI_STATUS_SYSEX_START = 0xF0, - MIDI_STATUS_SYSEX_END = 0xF7, - - //------------- System Common -------------// - MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, - MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, - MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, - // F4, F5 is undefined - MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, - - //------------- System RealTime -------------// - MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, - // 0xF9 is undefined - MIDI_STATUS_SYSREAL_START = 0xFA, - MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, - MIDI_STATUS_SYSREAL_STOP = 0xFC, - // 0xFD is undefined - MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, - MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, -}; - -/// MIDI Interface Header Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal - uint16_t wTotalLength ; -} midi_desc_header_t; - -/// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t iJack ; ///< string descriptor -} midi_desc_in_jack_t; - - -/// MIDI Out Jack Descriptor with single pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t bNrInputPins; - - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t iJack ; ///< string descriptor -} midi_desc_out_jack_t ; - -/// MIDI Out Jack Descriptor with multiple pins -#define midi_desc_out_jack_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bJackType ; \ - uint8_t bJackID ; \ - uint8_t bNrInputPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t iJack ; \ - } - -/// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bElementID; - - uint8_t bNrInputPins; - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t bNrOutputPins; - uint8_t bInTerminalLink; - uint8_t bOutTerminalLink; - uint8_t bElCapsSize; - - uint16_t bmElementCaps; - uint8_t iElement; -} midi_desc_element_t; - -/// MIDI Element Descriptor with multiple pins -#define midi_desc_element_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bDescriptorSubType; \ - uint8_t bElementID; \ - uint8_t bNrInputPins; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t bNrOutputPins; \ - uint8_t bInTerminalLink; \ - uint8_t bOutTerminalLink; \ - uint8_t bElCapsSize; \ - uint16_t bmElementCaps; \ - uint8_t iElement; \ - } - -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.c deleted file mode 100644 index e3e7826d..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_MIDI) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "midi_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -}midid_stream_t; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - -} midid_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; - -bool tud_midi_n_mounted (uint8_t itf) -{ - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} - -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - uint8_t const rhport = 0; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= sizeof(p_midi->epout_buf) ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t const* stream = &midi->stream_read; - - // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index); -} - -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ - (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - - uint32_t total_read = 0; - while( bufsize ) - { - // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - - uint8_t const code_index = stream->buffer[0] & 0x0f; - - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; - - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; - - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; - - default: - stream->total = 3; - break; - } - } - - // Copy data up to bufsize - uint8_t const count = (uint8_t) tu_min32(stream->total - stream->index, bufsize); - - // Skip the header (1st byte) in the buffer - TU_VERIFY(0 == tu_memcpy_s(buf8, bufsize, stream->buffer + 1 + stream->index, count)); - - total_read += count; - stream->index += count; - buf8 += count; - bufsize -= count; - - // complete current event packet, reset stream - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; - } - } - - return total_read; -} - -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); - - uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(midi); - return (num_read == 4); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -static uint32_t write_flush(midid_interface_t* midi) -{ - // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) return 0; - - uint8_t const rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) - { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midid_stream_t* stream = &midi->stream_write; - - uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { - uint8_t const data = buffer[i]; - i++; - - if ( stream->index == 0 ) - { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if ( ((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - stream->total = 2; - } - else - { - stream->total = 4; - } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { - // Channel Voice Messages - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 3; - } - else if ( msg == 0xf ) - { - // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - stream->buffer[0] |= (uint8_t)(cable_num << 4); - } - else - { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } - else - { - //------------- On-going (buffering) packet -------------// - - TU_ASSERT(stream->index < 4, i); - stream->buffer[stream->index] = data; - stream->index++; - - // See if this byte ends a SysEx. - if ( (stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); - stream->total = stream->index; - } - } - - // Send out packet - if ( stream->index == stream->total ) - { - // zeroes unused bytes - for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - } - - write_flush(midi); - - return i; -} - -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); - - if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(midi); - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void midid_init(void) -{ - tu_memclr(_midid_itf, sizeof(_midid_itf)); - - for(uint8_t i=0; irx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. - - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); - #endif - } -} - -void midid_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&midi->tx_ff); - } -} - -uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); - - uint16_t drv_len = tu_desc_len(desc_itf); - uint8_t const * p_desc = tu_desc_next(desc_itf); - - // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); - - // Find available interface - midid_interface_t * p_midi = NULL; - for(uint8_t i=0; iitf_num = desc_midi->bInterfaceNumber; - (void) p_midi->itf_num; - - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } - - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // Prepare for incoming data - _prep_out_transaction(p_midi); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - (void) rhport; - (void) stage; - (void) request; - - // driver doesn't support any request yet - return false; -} - -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t itf; - midid_interface_t* p_midi; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_MIDI; itf++) - { - p_midi = &_midid_itf[itf]; - if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_MIDI); - - // receive new data - if ( ep_addr == p_midi->ep_out ) - { - tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, (uint16_t) xferred_bytes); - - // invoke receive callback if available - if (tud_midi_rx_cb) tud_midi_rx_cb(itf); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(p_midi); - } - else if ( ep_addr == p_midi->ep_in ) - { - if (0 == write_flush(p_midi)) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) - { - if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) - { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } - } - } - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.h deleted file mode 100644 index 1c6f996b..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/midi/midi_device.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ - -#include "class/audio/audio.h" -#include "midi.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) - #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE -#endif - -#ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_MIDI > 1 -//--------------------------------------------------------------------+ - -// Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); - -// Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); - -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} - -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} - - -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} - -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ - return tud_midi_n_mounted(0); -} - -static inline uint32_t tud_midi_available (void) -{ - return tud_midi_n_available(0, 0); -} - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_read(0, 0, buffer, bufsize); -} - -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); -} - -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ - return tud_midi_n_packet_read(0, packet); -} - -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ - return tud_midi_n_packet_write(0, packet); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc.h b/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc.h deleted file mode 100644 index 7f25a29b..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Mass Storage Class Constant -//--------------------------------------------------------------------+ -/// MassStorage Subclass -typedef enum -{ - MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D - MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device - MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device - MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SCSI ///< SCSI transparent command set -}msc_subclass_type_t; - -enum { - MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian) - MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian) -}; - -/// \brief MassStorage Protocol. -/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy -typedef enum -{ - MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt) - MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt) - MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport -}msc_protocol_type_t; - -/// MassStorage Class-Specific Control Request -typedef enum -{ - MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15 - MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host. -}msc_request_type_t; - -/// \brief Command Block Status Values -/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed -/// successfully. A non-zero value shall indicate a failure during command execution according to the following -typedef enum -{ - MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED - MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED - MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR -}msc_csw_status_t; - -/// Command Block Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW. - uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW. - uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags. - uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host. - uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero. - uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16 - uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block -}msc_cbw_t; - -TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); - -/// Command Status Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW. - uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW. - uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device - uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t -}msc_csw_t; - -TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Constant -//--------------------------------------------------------------------+ - -/// SCSI Command Operation Code -typedef enum -{ - SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation. - SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device. - SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters. - SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command. - SCSI_CMD_START_STOP_UNIT = 0x1B, - SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, - SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device. - SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device. - SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed - SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. - SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them. -}scsi_cmd_type_t; - -/// SCSI Sense Key -typedef enum -{ - SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command - SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive. - SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed. - SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition. - SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test. - SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters - SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset. - SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed. - SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key. - SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command. - SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison. - SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium. - SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium. -}scsi_sense_key_type_t; - -//--------------------------------------------------------------------+ -// SCSI Primary Command (SPC-4) -//--------------------------------------------------------------------+ - -/// SCSI Test Unit Ready Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY - uint8_t lun ; ///< Logical Unit - uint8_t reserved[3] ; - uint8_t control ; -} scsi_test_unit_ready_t; - -TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); - -/// SCSI Inquiry Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY - uint8_t reserved1 ; - uint8_t page_code ; - uint8_t reserved2 ; - uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred. - uint8_t control ; -} scsi_inquiry_t, scsi_request_sense_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); - -/// SCSI Inquiry Response Data -typedef struct TU_ATTR_PACKED -{ - uint8_t peripheral_device_type : 5; - uint8_t peripheral_qualifier : 3; - - uint8_t : 7; - uint8_t is_removable : 1; - - uint8_t version; - - uint8_t response_data_format : 4; - uint8_t hierarchical_support : 1; - uint8_t normal_aca : 1; - uint8_t : 2; - - uint8_t additional_length; - - uint8_t protect : 1; - uint8_t : 2; - uint8_t third_party_copy : 1; - uint8_t target_port_group_support : 2; - uint8_t access_control_coordinator : 1; - uint8_t scc_support : 1; - - uint8_t addr16 : 1; - uint8_t : 3; - uint8_t multi_port : 1; - uint8_t : 1; // vendor specific - uint8_t enclosure_service : 1; - uint8_t : 1; - - uint8_t : 1; // vendor specific - uint8_t cmd_que : 1; - uint8_t : 2; - uint8_t sync : 1; - uint8_t wbus16 : 1; - uint8_t : 2; - - uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product. - uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor. - uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. -} scsi_inquiry_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); - - -typedef struct TU_ATTR_PACKED -{ - uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format - uint8_t valid : 1; - - uint8_t reserved; - - uint8_t sense_key : 4; - uint8_t : 1; - uint8_t ili : 1; ///< Incorrect length indicator - uint8_t end_of_medium : 1; - uint8_t filemark : 1; - - uint32_t information; - uint8_t add_sense_len; - uint32_t command_specific_info; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; - uint8_t field_replaceable_unit_code; - - uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout - -} scsi_sense_fixed_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6 - - uint8_t : 3; - uint8_t disable_block_descriptor : 1; - uint8_t : 4; - - uint8_t page_code : 6; - uint8_t page_control : 2; - - uint8_t subpage_code; - uint8_t alloc_length; - uint8_t control; -} scsi_mode_sense6_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); - -// This is only a Mode parameter header(6). -typedef struct TU_ATTR_PACKED -{ - uint8_t data_len; - uint8_t medium_type; - - uint8_t reserved : 7; - bool write_protected : 1; - - uint8_t block_descriptor_len; -} scsi_mode_sense6_resp_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL - uint8_t reserved[3]; - uint8_t prohibit_removal; - uint8_t control; -} scsi_prevent_allow_medium_removal_t; - -TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - - uint8_t immded : 1; - uint8_t : 7; - - uint8_t TU_RESERVED; - - uint8_t power_condition_mod : 4; - uint8_t : 4; - - uint8_t start : 1; - uint8_t load_eject : 1; - uint8_t no_flush : 1; - uint8_t : 1; - uint8_t power_condition : 4; - - uint8_t control; -} scsi_start_stop_unit_t; - -TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI MMC -//--------------------------------------------------------------------+ -/// SCSI Read Format Capacity: Write Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - uint8_t reserved[6]; - uint16_t alloc_length; - uint8_t control; -} scsi_read_format_capacity_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); - -typedef struct TU_ATTR_PACKED{ - uint8_t reserved[3]; - uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it. - - uint32_t block_num; /// Number of Logical Blocks - uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present - - uint8_t reserved2; - uint16_t block_size_u16; - -} scsi_read_format_capacity_data_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Block Command (SBC-3) -// NOTE: All data in SCSI command are in Big Endian -//--------------------------------------------------------------------+ - -/// SCSI Read Capacity 10 Command: Read Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10 - uint8_t reserved1 ; - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint16_t reserved2 ; - uint8_t partial_medium_indicator ; - uint8_t control ; -} scsi_read_capacity10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); - -/// SCSI Read Capacity 10 Response Data -typedef struct { - uint32_t last_lba ; ///< The last Logical Block Address of the device - uint32_t block_size ; ///< Block size in bytes -} scsi_read_capacity10_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); - -/// SCSI Read 10 Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode - uint8_t reserved ; // has LUN according to wiki - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint8_t reserved2 ; - uint16_t block_count ; ///< Number of Blocks used by this command - uint8_t control ; -} scsi_read10_t, scsi_write10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.c deleted file mode 100644 index 159a1125..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_MSC) - -#include "device/dcd.h" // for faking dcd_event_xfer_complete -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "msc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Can be selectively disabled to reduce logging when troubleshooting other driver -#define MSC_DEBUG 2 - -enum -{ - MSC_STAGE_CMD = 0, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, - MSC_STAGE_STATUS_SENT, - MSC_STAGE_NEED_RESET, -}; - -typedef struct -{ - // TODO optimize alignment - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw - uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - - // Sense Response Data - uint8_t sense_key; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; -}mscd_interface_t; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); - -TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) -{ - return tu_bit_test(dir, 7); -} - -static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) -{ - // Data residue is always = host expect - actual transferred - p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - - p_msc->stage = MSC_STAGE_STATUS_SENT; - return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); -} - -static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); -} - -static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - p_csw->status = status; - p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - p_msc->stage = MSC_STAGE_STATUS; - - // failed but sense key is not set: default to Illegal Request - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - // If there is data stage and not yet complete, stall it - if ( p_cbw->total_bytes && p_csw->data_residue ) - { - if ( is_data_in(p_cbw->dir) ) - { - usbd_edpt_stall(rhport, p_msc->ep_in); - } - else - { - usbd_edpt_stall(rhport, p_msc->ep_out); - } - } -} - -static inline uint32_t rdwr10_get_lba(uint8_t const command[]) -{ - // use offsetof to avoid pointer to the odd/unaligned address - uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - - // lba is in Big Endian - return tu_ntohl(lba); -} - -static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) -{ - uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); - return tu_ntohs(block_count); -} - -static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) -{ - // first extract block count in the command - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - // invalid block count - if (block_count == 0) return 0; - - return (uint16_t) (cbw->total_bytes / block_count); -} - -uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) -{ - uint8_t status = MSC_CSW_STATUS_PASSED; - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - if ( cbw->total_bytes == 0 ) - { - if ( block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - }else - { - // no data transfer, only exist in complaint test suite - } - }else - { - if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( 0 == block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); - status = MSC_CSW_STATUS_FAILED; - } - else if ( cbw->total_bytes / block_count == 0 ) - { - TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - } - - return status; -} - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = -{ - { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, - { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, - { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, - { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, - { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, - { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent/Allow Medium Removal" }, - { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, - { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, - { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, - { .key = SCSI_CMD_READ_10 , .data = "Read10" }, - { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } -}; - -TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table = -{ - .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), - .items = _msc_scsi_cmd_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) -{ - (void) lun; - - _mscd_itf.sense_key = sense_key; - _mscd_itf.add_sense_code = add_sense_code; - _mscd_itf.add_sense_qualifier = add_sense_qualifier; - - return true; -} - -static inline void set_sense_medium_not_present(uint8_t lun) -{ - // default sense is NOT READY, MEDIUM NOT PRESENT - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void mscd_init(void) -{ - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -void mscd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // only support SCSI's BOT protocol - TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && - MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - - // Max length must be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= drv_len, 0); - - mscd_interface_t * p_msc = &_mscd_itf; - p_msc->itf_num = itf_desc->bInterfaceNumber; - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - - // Prepare for Command Block Wrapper - TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); - - return drv_len; -} - -static void proc_bot_reset(mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - p_msc->total_len = 0; - p_msc->xferred_len = 0; - - p_msc->sense_key = 0; - p_msc->add_sense_code = 0; - p_msc->add_sense_qualifier = 0; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - mscd_interface_t* p_msc = &_mscd_itf; - - // Clear Endpoint Feature (stall) for recovery - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && - TUSB_REQ_CLEAR_FEATURE == request->bRequest && - TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) - { - uint8_t const ep_addr = tu_u16_low(request->wIndex); - - if ( p_msc->stage == MSC_STAGE_NEED_RESET ) - { - // reset recovery is required to recover from this stage - // Clear Stall request cannot resolve this -> continue to stall endpoint - usbd_edpt_stall(rhport, ep_addr); - } - else - { - if ( ep_addr == p_msc->ep_in ) - { - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // resume sending SCSI status if we are in this stage previously before stalled - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - else if ( ep_addr == p_msc->ep_out ) - { - if ( p_msc->stage == MSC_STAGE_CMD ) - { - // part of reset recovery (probably due to invalid CBW) -> prepare for new command - // Note: skip if already queued previously - if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) - { - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - } - } - } - } - - return true; - } - - // From this point only handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch ( request->bRequest ) - { - case MSC_REQ_RESET: - TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 0); - - // driver state reset - proc_bot_reset(p_msc); - - tud_control_status(rhport, request); - break; - - case MSC_REQ_GET_MAX_LUN: - { - TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 1); - - uint8_t maxlun = 1; - if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); - TU_VERIFY(maxlun); - - // MAX LUN is minus 1 by specs - maxlun--; - - tud_control_xfer(rhport, request, &maxlun, 1); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) event; - - mscd_interface_t* p_msc = &_mscd_itf; - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it - if(ep_addr != p_msc->ep_out) return true; - - if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) - { - TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); - - // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery - p_msc->stage = MSC_STAGE_NEED_RESET; - - // invalid CBW stall both endpoints - usbd_edpt_stall(rhport, p_msc->ep_in); - usbd_edpt_stall(rhport, p_msc->ep_out); - - return false; - } - - TU_LOG(MSC_DEBUG, " SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); - - p_csw->signature = MSC_CSW_SIGNATURE; - p_csw->tag = p_cbw->tag; - p_csw->data_residue = 0; - p_csw->status = MSC_CSW_STATUS_PASSED; - - /*------------- Parse command and prepare DATA -------------*/ - p_msc->stage = MSC_STAGE_DATA; - p_msc->total_len = p_cbw->total_bytes; - p_msc->xferred_len = 0; - - // Read10 or Write10 - if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) - { - uint8_t const status = rdwr10_validate_cmd(p_cbw); - - if ( status != MSC_CSW_STATUS_PASSED) - { - fail_scsi_op(rhport, p_msc, status); - }else if ( p_cbw->total_bytes ) - { - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - proc_read10_cmd(rhport, p_msc); - }else - { - proc_write10_cmd(rhport, p_msc); - } - }else - { - // no data transfer, only exist in complaint test suite - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - // For other SCSI commands - // 1. OUT : queue transfer (invoke app callback after done) - // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length - if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) - { - if (p_cbw->total_bytes > sizeof(_mscd_buf)) - { - TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first - // but it is OK to just receive data then responded with failed status - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, (uint16_t) p_msc->total_len) ); - } - }else - { - // First process if it is a built-in commands - int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - - // Invoke user callback if not built-in - if ( (resplen < 0) && (p_msc->sense_key == 0) ) - { - resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); - } - - if ( resplen < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported or failed command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if (resplen == 0) - { - if (p_cbw->total_bytes) - { - // 6.7 The 13 Cases: case 4 (Hi > Dn) - // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // case 1 Hn = Dn: all good - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - if ( p_cbw->total_bytes == 0 ) - { - // 6.7 The 13 Cases: case 2 (Hn < Di) - // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // cannot return more than host expect - p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) p_msc->total_len) ); - } - } - } - } - break; - - case MSC_STAGE_DATA: - TU_LOG(MSC_DEBUG, " SCSI Data [Lun%u]\r\n", p_cbw->lun); - //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); - - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - proc_read10_cmd(rhport, p_msc); - } - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_new_data(rhport, p_msc, xferred_bytes); - } - else - { - p_msc->xferred_len += xferred_bytes; - - // OUT transfer, invoke callback if needed - if ( !is_data_in(p_cbw->dir) ) - { - int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len); - - if ( cb_result < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // TODO haven't implement this scenario any further yet - } - } - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - } - else - { - // This scenario with command that take more than one transfer is already rejected at Command stage - TU_BREAKPOINT(); - } - } - break; - - case MSC_STAGE_STATUS: - // processed immediately after this switch, supposedly to be empty - break; - - case MSC_STAGE_STATUS_SENT: - // Wait for the Status phase to complete - if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) - { - TU_LOG(MSC_DEBUG, " SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status); - // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); - - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - }else - { - // Any xfer ended here is consider unknown error, ignore it - TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); - } - break; - - default : break; - } - - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // skip status if epin is currently stalled, will do it when received Clear Stall request - if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) - { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - }else - { - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(rhport, p_msc); - } - #endif - } - - return true; -} - -/*------------------------------------------------------------------*/ -/* SCSI Command Process - *------------------------------------------------------------------*/ - -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - mscd_interface_t* p_msc = &_mscd_itf; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_capa10, (size_t) resplen)); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // set default sense if not set by callback - if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_fmt_capa, (size_t) resplen)); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - .additional_length = sizeof(scsi_inquiry_resp_t) - 5, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &inquiry_rsp, (size_t) resplen)); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(lun); - } - - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &mode_resp, (size_t) resplen)); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, // current, fixed format - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - sense_rsp.sense_key = (uint8_t) (p_msc->sense_key & 0x0F); - sense_rsp.add_sense_code = p_msc->add_sense_code; - sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; - - resplen = sizeof(sense_rsp); - TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &sense_rsp, (size_t) resplen)); - - // request sense callback could overwrite the sense data - if (tud_msc_request_sense_cb) - { - resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t) bufsize); - } - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Application can consume smaller bytes - uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); - - if ( nbytes < 0 ) - { - // negative means error -> endpoint is stalled & status in CSW set to failed - TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); - - // set sense - set_sense_medium_not_present(p_cbw->lun); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if ( nbytes == 0 ) - { - // zero means not ready -> simulate an transfer complete so that this driver callback will fired again - dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); - } - else - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) nbytes), ); - } -} - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - bool writable = true; - - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(p_cbw->lun); - } - - if ( !writable ) - { - // Not writable, complete this SCSI op with error - // Sense = Write protected - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - return; - } - - // remaining bytes capped at class buffer - uint16_t nbytes = (uint16_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Write10 callback will be called later when usb transfer complete - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); -} - -// process new data arrived from WRITE10 -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Invoke callback to consume new data - uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); - - if ( nbytes < 0 ) - { - // negative means error -> failed this scsi op - TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); - - // update actual byte before failed - p_msc->xferred_len += xferred_bytes; - - // Set sense - set_sense_medium_not_present(p_cbw->lun); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Application consume less than what we got (including zero) - if ( (uint32_t) nbytes < xferred_bytes ) - { - uint32_t const left_over = xferred_bytes - (uint32_t) nbytes; - if ( nbytes > 0 ) - { - p_msc->xferred_len += (uint16_t) nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, left_over); - } - - // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter - dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); - } - else - { - // Application consume all bytes in our buffer - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - // prepare to receive more data from host - proc_write10_cmd(rhport, p_msc); - } - } - } -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.h deleted file mode 100644 index 72f95be0..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_device.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE -#endif - -#ifndef CFG_TUD_MSC_EP_BUFSIZE - #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better -#endif - -TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Set SCSI sense response -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If -// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. -// -// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If -// - write < bufsize : callback invoked again with remaining data later on. -// -// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// TODO change buffer to const uint8_t* -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); - -// Invoked when received SCSI_CMD_INQUIRY -// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun); - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); - -/** - * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE - * - READ10 and WRITE10 has their own callbacks - * - * \param[in] lun Logical unit number - * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly - * \param[out] buffer Buffer for SCSI Data Stage. - * - For INPUT: application must fill this with response. - * - For OUTPUT it holds the Data from host - * \param[in] bufsize Buffer's length. - * - * \return Actual bytes processed, can be zero for no-data command. - * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); - -/*------------- Optional callbacks -------------*/ - -// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation -TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); - -// Invoked when received REQUEST_SENSE -TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize); - -// Invoked when Read10 command is complete -TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); - -// Invoke when Write10 command is complete, can be used to flush flash caching -TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); - -// Invoked when command in tud_msc_scsi_cb is complete -TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); - -// Invoked to check if device is writable as part of SCSI WRITE10 -TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.c b/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.c deleted file mode 100644 index 1b48813e..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if CFG_TUH_ENABLED && CFG_TUH_MSC - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "msc_host.h" - -// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message -#define MSCH_DEBUG 2 - -#define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__) - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - MSC_STAGE_IDLE = 0, - MSC_STAGE_CMD, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - - volatile bool configured; // Receive SET_CONFIGURE - volatile bool mounted; // Enumeration is complete - - struct { - uint32_t block_size; - uint32_t block_count; - } capacity[CFG_TUH_MSC_MAXLUN]; - - //------------- SCSI -------------// - uint8_t stage; - void* buffer; - tuh_msc_complete_cb_t complete_cb; - uintptr_t complete_arg; - - CFG_TUH_MEM_ALIGN msc_cbw_t cbw; - CFG_TUH_MEM_ALIGN msc_csw_t csw; -}msch_interface_t; - -CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; - -// buffer used to read scsi information when mounted -// largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN -static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; -} - -//--------------------------------------------------------------------+ -// PUBLIC API -//--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->max_lun; -} - -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_count; -} - -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_size; -} - -bool tuh_msc_mounted(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted; -} - -bool tuh_msc_ready(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); -} - -//--------------------------------------------------------------------+ -// PUBLIC API: SCSI COMMAND -//--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ - tu_memclr(cbw, sizeof(msc_cbw_t)); - cbw->signature = MSC_CBW_SIGNATURE; - cbw->tag = 0x54555342; // TUSB - cbw->lun = lun; -} - -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - // TODO claim endpoint - - p_msc->cbw = *cbw; - p_msc->stage = MSC_STAGE_CMD; - p_msc->buffer = data; - p_msc->complete_cb = complete_cb; - p_msc->complete_arg = arg; - - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); - - return true; -} - -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read_capacity10_t); - cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_inquiry_t); - - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) - }; - memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification - - return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg); -} - -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); - - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; - - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); -} - -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); - - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg); -} - -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); - - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg); -} - -#if 0 -// MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBH API -//--------------------------------------------------------------------+ -void msch_init(void) -{ - tu_memclr(_msch_itf, sizeof(_msch_itf)); -} - -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); - - tu_memclr(p_msc, sizeof(msch_interface_t)); -} - -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - msc_cbw_t const * cbw = &p_msc->cbw; - msc_csw_t * csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - - if ( cbw->total_bytes && p_msc->buffer ) - { - // Data stage if any - p_msc->stage = MSC_STAGE_DATA; - - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; - TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes)); - }else - { - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - } - break; - - case MSC_STAGE_DATA: - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - break; - - case MSC_STAGE_STATUS: - // SCSI op is complete - p_msc->stage = MSC_STAGE_IDLE; - - if (p_msc->complete_cb) - { - tuh_msc_complete_data_t const cb_data = - { - .cbw = cbw, - .csw = csw, - .scsi_data = p_msc->buffer, - .user_arg = p_msc->complete_arg - }; - p_msc->complete_cb(dev_addr, &cb_data); - } - break; - - // unknown state - default: break; - } - - return true; -} - -//--------------------------------------------------------------------+ -// MSC Enumeration -//--------------------------------------------------------------------+ - -static void config_get_maxlun_complete (tuh_xfer_t* xfer); -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data); -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); - -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) rhport; - TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); - - // msc driver length is fixed - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(drv_len <= max_len); - - msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); - - for(uint32_t i=0; i<2; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); - - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { - p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { - p_msc->ep_out = ep_desc->bEndpointAddress; - } - - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); - } - - p_msc->itf_num = desc_itf->bInterfaceNumber; - - return true; -} - -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_ASSERT(p_msc->itf_num == itf_num); - - p_msc->configured = true; - - //------------- Get Max Lun -------------// - TU_LOG_MSCH("MSC Get Max Lun\r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 - }; - - tuh_xfer_t xfer = - { - .daddr = dev_addr, - .ep_addr = 0, - .setup = &request, - .buffer = &p_msc->max_lun, - .complete_cb = config_get_maxlun_complete, - .user_data = 0 - }; - TU_ASSERT(tuh_control_xfer(&xfer)); - - return true; -} - -static void config_get_maxlun_complete (tuh_xfer_t* xfer) -{ - uint8_t const daddr = xfer->daddr; - msch_interface_t* p_msc = get_itf(daddr); - - // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0; - p_msc->max_lun++; // MAX LUN is minus 1 by specs - - // TODO multiple LUN support - TU_LOG_MSCH("SCSI Test Unit Ready\r\n"); - uint8_t const lun = 0; - tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0); -} - -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - if (csw->status == 0) - { - // Unit is ready, read its capacity - TU_LOG_MSCH("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0); - }else - { - // Note: During enumeration, some device fails Test Unit Ready and require a few retries - // with Request Sense to start working !! - // TODO limit number of retries - TU_LOG_MSCH("SCSI Request Sense\r\n"); - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete, 0)); - } - - return true; -} - -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete, 0)); - return true; -} - -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ - msc_cbw_t const* cbw = cb_data->cbw; - msc_csw_t const* csw = cb_data->csw; - - TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); - p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; - p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); - - // Mark enumeration is complete - p_msc->mounted = true; - if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.h b/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.h deleted file mode 100644 index 6c0e5c9d..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/msc/msc_host.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ - -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUH_MSC_MAXLUN -#define CFG_TUH_MSC_MAXLUN 4 -#endif - -typedef struct { - msc_cbw_t const* cbw; // SCSI command - msc_csw_t const* csw; // SCSI status - void* scsi_data; // SCSI Data - uintptr_t user_arg; // user argument -}tuh_msc_complete_data_t; - -typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Check if device supports MassStorage interface. -// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() -bool tuh_msc_mounted(uint8_t dev_addr); - -// Check if the interface is currently ready or busy transferring data -bool tuh_msc_ready(uint8_t dev_addr); - -// Get Max Lun -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); - -// Get number of block -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); - -// Get block size in bytes -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); - -// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// Complete callback is invoked when SCSI op is complete. -// return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Inquiry command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Test Unit Ready command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Request Sense 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Write 10 command. Write n blocks starting from LBA to device -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by -// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); - -//------------- Application Callback -------------// - -// Invoked when a device with MassStorage interface is mounted -TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); - -// Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ - -void msch_init (void); -bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -void msch_close (uint8_t dev_addr); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_HOST_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/net/ecm_rndis_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/net/ecm_rndis_device.c deleted file mode 100644 index 8ac7cbd0..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/net/ecm_rndis_device.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( CFG_TUD_ENABLED && CFG_TUD_ECM_RNDIS ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "net_device.h" -#include "rndis_protocol.h" - -void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - bool ecm_mode; - - // Endpoint descriptor use to open/close when receiving SetInterface - // TODO since configuration descriptor may not be long-lived memory, we should - // keep a copy of endpoint attribute instead - uint8_t const * ecm_desc_epdata; - -} netd_interface_t; - -#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) -#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static -uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static -uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -tu_static const struct ecm_notify_struct ecm_notify_nc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -tu_static const struct ecm_notify_struct ecm_notify_csc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, - .wLength = 8, - }, - .downlink = 9728000, - .uplink = 9728000, -}; - -// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union -{ - uint8_t rndis_buf[120]; - struct ecm_notify_struct ecm_buf; -} notify; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// TODO remove CFG_TUSB_MEM_SECTION -CFG_TUSB_MEM_SECTION tu_static netd_interface_t _netd_itf; - -tu_static bool can_xmit; - -void tud_network_recv_renew(void) -{ - usbd_edpt_xfer(0, _netd_itf.ep_out, received, sizeof(received)); -} - -static void do_in_xfer(uint8_t *buf, uint16_t len) -{ - can_xmit = false; - usbd_edpt_xfer(0, _netd_itf.ep_in, buf, len); -} - -void netd_report(uint8_t *buf, uint16_t len) -{ - uint8_t const rhport = 0; - - // skip if previous report not yet acknowledged by host - if ( usbd_edpt_busy(rhport, _netd_itf.ep_notif) ) return; - usbd_edpt_xfer(rhport, _netd_itf.ep_notif, buf, len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void netd_init(void) -{ - tu_memclr(&_netd_itf, sizeof(_netd_itf)); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && - TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); - - TU_VERIFY(is_rndis || is_ecm, 0); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif, 0); - - // sanity check the descriptor - _netd_itf.ecm_mode = is_ecm; - - //------------- Management Interface -------------// - _netd_itf.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - RNDIS Data followed immediately by a pair of endpoints - // - CDC-ECM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for active networking - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - if ( _netd_itf.ecm_mode ) - { - // ECM by default is in-active, save the endpoint attribute - // to open later when received setInterface - _netd_itf.ecm_desc_epdata = p_desc; - }else - { - // Open endpoint pair for RNDIS - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); - - tud_network_init_cb(); - - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); - } - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ecm_report(bool nc) -{ - notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; - notify.ecm_buf.header.wIndex = _netd_itf.itf_num; - netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); - - _netd_itf.itf_data_alt = req_alt; - - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) - { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets - } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, (uint16_t) sizeof(notify.rndis_buf)); - } - } - break; - - // unsupported request - default: return false; - } - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - } - - return true; -} - -static void handle_incoming_packet(uint32_t len) -{ - uint8_t *pnt = received; - uint32_t size = 0; - - if (_netd_itf.ecm_mode) - { - size = len; - } - else - { - rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } - } - - if (!tud_network_recv_cb(pnt, (uint16_t) size)) - { - /* if a buffer was never handled by user code, we must renew on the user's behalf */ - tud_network_recv_renew(); - } -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new packet received */ - if ( ep_addr == _netd_itf.ep_out ) - { - handle_incoming_packet(xferred_bytes); - } - - /* data transmission finished */ - if ( ep_addr == _netd_itf.ep_in ) - { - /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ - - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) - { - do_in_xfer(NULL, 0); /* a ZLP is needed */ - } - else - { - /* we're finally finished */ - can_xmit = true; - } - } - - if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) - { - if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); - } - - return true; -} - -bool tud_network_can_xmit(uint16_t size) -{ - (void)size; - - return can_xmit; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - uint8_t *data; - uint16_t len; - - if (!can_xmit) - return; - - len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; - data = transmitted + len; - - len += tud_network_xmit_cb(data, ref, arg); - - if (!_netd_itf.ecm_mode) - { - rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); - } - - do_in_xfer(transmitted, len); -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm.h b/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm.h deleted file mode 100644 index 96ba11fb..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// Table 4.3 Data Class Interface Protocol Codes -typedef enum -{ - NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 -} ncm_data_interface_protocol_code_t; - - -// Table 6.2 Class-Specific Request Codes for Network Control Model subclass -typedef enum -{ - NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - NCM_SET_ETHERNET_PACKET_FILTER = 0x43, - NCM_GET_ETHERNET_STATISTIC = 0x44, - NCM_GET_NTB_PARAMETERS = 0x80, - NCM_GET_NET_ADDRESS = 0x81, - NCM_SET_NET_ADDRESS = 0x82, - NCM_GET_NTB_FORMAT = 0x83, - NCM_SET_NTB_FORMAT = 0x84, - NCM_GET_NTB_INPUT_SIZE = 0x85, - NCM_SET_NTB_INPUT_SIZE = 0x86, - NCM_GET_MAX_DATAGRAM_SIZE = 0x87, - NCM_SET_MAX_DATAGRAM_SIZE = 0x88, - NCM_GET_CRC_MODE = 0x89, - NCM_SET_CRC_MODE = 0x8A, -} ncm_request_code_t; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm_device.c deleted file mode 100644 index 9e958024..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/net/ncm_device.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jacob Berg Potter - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( CFG_TUD_ENABLED && CFG_TUD_NCM ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "net_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -#define NTH16_SIGNATURE 0x484D434E -#define NDP16_SIGNATURE_NCM0 0x304D434E -#define NDP16_SIGNATURE_NCM1 0x314D434E - -typedef struct TU_ATTR_PACKED -{ - uint16_t wLength; - uint16_t bmNtbFormatsSupported; - uint32_t dwNtbInMaxSize; - uint16_t wNdbInDivisor; - uint16_t wNdbInPayloadRemainder; - uint16_t wNdbInAlignment; - uint16_t wReserved; - uint32_t dwNtbOutMaxSize; - uint16_t wNdbOutDivisor; - uint16_t wNdbOutPayloadRemainder; - uint16_t wNdbOutAlignment; - uint16_t wNtbOutMaxDatagrams; -} ntb_parameters_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wHeaderLength; - uint16_t wSequence; - uint16_t wBlockLength; - uint16_t wNdpIndex; -} nth16_t; - -typedef struct TU_ATTR_PACKED -{ - uint16_t wDatagramIndex; - uint16_t wDatagramLength; -} ndp16_datagram_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wLength; - uint16_t wNextNdpIndex; - ndp16_datagram_t datagram[]; -} ndp16_t; - -typedef union TU_ATTR_PACKED { - struct { - nth16_t nth; - ndp16_t ndp; - }; - uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; -} transmit_ntb_t; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - const ndp16_t *ndp; - uint8_t num_datagrams, current_datagram_index; - - enum { - REPORT_SPEED, - REPORT_CONNECTED, - REPORT_DONE - } report_state; - bool report_pending; - - uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams - uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] - uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram - uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE - uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB - - uint16_t nth_sequence; // Sequence number counter for transmitted NTBs - - bool transferring; - -} ncm_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = { - .wLength = sizeof(ntb_parameters_t), - .bmNtbFormatsSupported = 0x01, - .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, - .wNdbInDivisor = 4, - .wNdbInPayloadRemainder = 0, - .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, - .wReserved = 0, - .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, - .wNdbOutDivisor = 4, - .wNdbOutPayloadRemainder = 0, - .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, - .wNtbOutMaxDatagrams = 0 -}; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static transmit_ntb_t transmit_ntb[2]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; - -tu_static ncm_interface_t ncm_interface; - -/* - * Set up the NTB state in ncm_interface to be ready to add datagrams. - */ -static void ncm_prepare_for_tx(void) { - ncm_interface.datagram_count = 0; - // datagrams start after all the headers - ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) - + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); -} - -/* - * If not already transmitting, start sending the current NTB to the host and swap buffers - * to start filling the other one with datagrams. - */ -static void ncm_start_tx(void) { - if (ncm_interface.transferring) { - return; - } - - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t ntb_length = ncm_interface.next_datagram_offset; - - // Fill in NTB header - ntb->nth.dwSignature = NTH16_SIGNATURE; - ntb->nth.wHeaderLength = sizeof(nth16_t); - ntb->nth.wSequence = ncm_interface.nth_sequence++; - ntb->nth.wBlockLength = ntb_length; - ntb->nth.wNdpIndex = sizeof(nth16_t); - - // Fill in NDP16 header and terminator - ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; - ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); - ntb->ndp.wNextNdpIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; - - // Kick off an endpoint transfer - usbd_edpt_xfer(0, ncm_interface.ep_in, ntb->data, ntb_length); - ncm_interface.transferring = true; - - // Swap to the other NTB and clear it out - ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; - ncm_prepare_for_tx(); -} - -tu_static struct ecm_notify_struct ncm_notify_connected = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_NETWORK_CONNECTION, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -tu_static struct ecm_notify_struct ncm_notify_speed_change = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, - .wLength = 8, - }, - .downlink = 10000000, - .uplink = 10000000, -}; - -void tud_network_recv_renew(void) -{ - if (!ncm_interface.num_datagrams) - { - usbd_edpt_xfer(0, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); - return; - } - - const ndp16_t *ndp = ncm_interface.ndp; - const int i = ncm_interface.current_datagram_index; - ncm_interface.current_datagram_index++; - ncm_interface.num_datagrams--; - - tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ - -void netd_init(void) -{ - tu_memclr(&ncm_interface, sizeof(ncm_interface)); - ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; - ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; - ncm_prepare_for_tx(); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // confirm interface hasn't already been allocated - TU_ASSERT(0 == ncm_interface.ep_notif, 0); - - //------------- Management Interface -------------// - ncm_interface.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - CDC-NCM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for transfer of NTBs - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ncm_report(void) -{ - uint8_t const rhport = 0; - if (ncm_interface.report_state == REPORT_SPEED) { - ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); - ncm_interface.report_state = REPORT_CONNECTED; - ncm_interface.report_pending = true; - } else if (ncm_interface.report_state == REPORT_CONNECTED) { - ncm_notify_connected.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); - ncm_interface.report_state = REPORT_DONE; - ncm_interface.report_pending = true; - } -} - -TU_ATTR_WEAK void tud_network_link_state_cb(bool state) -{ - (void)state; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage != CONTROL_STAGE_SETUP ) return true; - - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); - - tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); - - if (req_alt != ncm_interface.itf_data_alt) { - ncm_interface.itf_data_alt = req_alt; - - if (ncm_interface.itf_data_alt) { - if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { - tud_network_recv_renew(); // prepare for incoming datagrams - } - if (!ncm_interface.report_pending) { - ncm_report(); - } - } - - tud_network_link_state_cb(ncm_interface.itf_data_alt); - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (ncm_interface.itf_num == request->wIndex); - - if (NCM_GET_NTB_PARAMETERS == request->bRequest) - { - tud_control_xfer(rhport, request, (void*)(uintptr_t) &ntb_parameters, sizeof(ntb_parameters)); - } - - break; - - // unsupported request - default: return false; - } - - return true; -} - -static void handle_incoming_datagram(uint32_t len) -{ - uint32_t size = len; - - if (len == 0) { - return; - } - - TU_ASSERT(size >= sizeof(nth16_t), ); - - const nth16_t *hdr = (const nth16_t *)receive_ntb; - TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); - TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); - - const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); - TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); - TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); - - int num_datagrams = (ndp->wLength - 12) / 4; - ncm_interface.current_datagram_index = 0; - ncm_interface.num_datagrams = 0; - ncm_interface.ndp = ndp; - for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) - { - ncm_interface.num_datagrams++; - } - - tud_network_recv_renew(); -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new datagram receive_ntb */ - if (ep_addr == ncm_interface.ep_out ) - { - handle_incoming_datagram(xferred_bytes); - } - - /* data transmission finished */ - if (ep_addr == ncm_interface.ep_in ) - { - if (ncm_interface.transferring) { - ncm_interface.transferring = false; - } - - // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now - if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { - ncm_start_tx(); - } - } - - if (ep_addr == ncm_interface.ep_notif ) - { - ncm_interface.report_pending = false; - ncm_report(); - } - - return true; -} - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size) -{ - TU_VERIFY(ncm_interface.itf_data_alt == 1); - - if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { - TU_LOG2("NTB full [by count]\r\n"); - return false; - } - - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - if (next_datagram_offset + size > ncm_interface.ntb_in_size) { - TU_LOG2("ntb full [by size]\r\n"); - return false; - } - - return true; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - - uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); - - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; - - ncm_interface.datagram_count++; - next_datagram_offset += size; - - // round up so the next datagram is aligned correctly - next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); - next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); - - ncm_interface.next_datagram_offset = next_datagram_offset; - - ncm_start_tx(); -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/net/net_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/net/net_device.h deleted file mode 100644 index 39991635..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/net/net_device.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ - -#include "class/cdc/cdc.h" - -#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM -#error "Cannot enable both ECM_RNDIS and NCM network drivers" -#endif - -#include "ncm.h" - -/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ -#ifndef CFG_TUD_NET_MTU -#define CFG_TUD_NET_MTU 1514 -#endif - -#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE -#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE -#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB -#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 -#endif - -#ifndef CFG_TUD_NCM_ALIGNMENT -#define CFG_TUD_NCM_ALIGNMENT 4 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// indicate to network driver that client has finished with the packet provided to network_recv_cb() -void tud_network_recv_renew(void); - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size); - -// if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(void *ref, uint16_t arg); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(const uint8_t *src, uint16_t size); - -// client must provide this: copy from network stack packet pointer to dst -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); - -//------------- ECM/RNDIS -------------// - -// client must provide this: initialize any network state back to the beginning -void tud_network_init_cb(void); - -// client must provide this: 48-bit MAC address -// TODO removed later since it is not part of tinyusb stack -extern uint8_t tud_network_mac_address[6]; - -//------------- NCM -------------// - -// callback to client providing optional indication of internal state of network driver -void tud_network_link_state_cb(bool state); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc.h b/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc.h deleted file mode 100644 index 090ab3c4..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc.h +++ /dev/null @@ -1,318 +0,0 @@ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ - -#include "common/tusb_common.h" - - -/* Implements USBTMC Revision 1.0, April 14, 2003 - - String descriptors must have a "LANGID=0x409"/US English string. - Characters must be 0x20 (' ') to 0x7E ('~') ASCII, - But MUST not contain: "/:?\* - Also must not have leading or trailing space (' ') - Device descriptor must state USB version 0x0200 or greater - - If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. -*/ - -#define USBTMC_VERSION 0x0100 -#define USBTMC_488_VERSION 0x0100 - -typedef enum { - USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, - USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, - USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, - USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, - USBTMC_MSGID_USB488_TRIGGER = 128u, -} usbtmc_msgid_enum; - -/// \brief Message header (For BULK OUT and BULK IN); 4 bytes -typedef struct TU_ATTR_PACKED -{ - uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) - uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 - uint8_t bTagInverse ; ///< Complement of the tag - uint8_t _reserved ; ///< Must be 0x00 -} usbtmc_msg_header_t; - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint8_t data[8]; -} usbtmc_msg_generic_t; - -/* Uses on the bulk-out endpoint: */ -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int EOM : 1 ; ///< EOM set on last byte - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_request_dev_dep_out; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); - -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar - } bmTransferAttributes; - uint8_t TermChar; - uint8_t _reserved[2]; -} usbtmc_msg_request_dev_dep_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); - -/* Bulk-in headers */ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint32_t TransferSize; - struct TU_ATTR_PACKED - { - uint8_t EOM: 1; ///< Last byte of transfer is the end of the message - uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_dev_dep_msg_in_header_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); - -/* Unsupported vendor things.... Are these ever used?*/ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_out; - - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); - -// Control request type should use tusb_control_request_t - -/* -typedef struct TU_ATTR_PACKED { - struct { - unsigned int Recipient : 5 ; ///< EOM set on last byte - unsigned int Type : 2 ; ///< EOM set on last byte - unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN - } bmRequestType; - uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum - uint16_t wValue ; - uint16_t wIndex ; - uint16_t wLength ; // Number of bytes in data stage -} usbtmc_class_specific_control_req; - -*/ -// bulk-in protocol errors -enum { - USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, - USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, - USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, - USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, - USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, -}; -// built-in halt errors -enum { - USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a - /// Bulk-IN transfer is in progress -}; - -typedef enum { - USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, - USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, - USBTMC_bREQUEST_INITIATE_CLEAR = 5u, - USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, - USBTMC_bREQUEST_GET_CAPABILITIES = 7u, - - USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional - - /****** USBTMC 488 *************/ - USB488_bREQUEST_READ_STATUS_BYTE = 128u, - USB488_bREQUEST_REN_CONTROL = 160u, - USB488_bREQUEST_GO_TO_LOCAL = 161u, - USB488_bREQUEST_LOCAL_LOCKOUT = 162u, - -} usmtmc_request_type_enum; - -typedef enum { - USBTMC_STATUS_SUCCESS = 0x01, - USBTMC_STATUS_PENDING = 0x02, - USBTMC_STATUS_FAILED = 0x80, - USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, - USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, - USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83, - - /****** USBTMC 488 *************/ - USB488_STATUS_INTERRUPT_IN_BUSY = 0x20 -} usbtmc_status_enum; - -/************************************************************ - * Control Responses - */ - -typedef struct TU_ATTR_PACKED { - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - uint8_t _reserved2[6]; - uint8_t _reserved3[12]; -} usbtmc_response_capabilities_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes :1; - } bmClear; -} usbtmc_get_clear_status_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both abort bulk IN and bulk OUT -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; -} usbtmc_initiate_abort_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued - } bmAbortBulkIn; - uint8_t _reserved[2]; ///< Must be zero - uint32_t NBYTES_RXD_TXD; -} usbtmc_check_abort_bulk_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; - } bmIntfcCapabilities; - - struct TU_ATTR_PACKED - { - uint8_t canEndBulkInOnTermChar :1; - } bmDevCapabilities; - - uint8_t _reserved2[6]; - uint16_t bcdUSB488; - - struct TU_ATTR_PACKED - { - uint8_t supportsTrigger :1; - uint8_t supportsREN_GTL_LLO :1; - uint8_t is488_2 :1; - } bmIntfcCapabilities488; - - struct TU_ATTR_PACKED - { - uint8_t DT1 :1; - uint8_t RL1 :1; - uint8_t SR1 :1; - uint8_t SCPI :1; - } bmDevCapabilities488; - uint8_t _reserved3[8]; -} usbtmc_response_capabilities_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; - uint8_t statusByte; -} usbtmc_read_stb_rsp_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - struct TU_ATTR_PACKED - { - unsigned int bTag : 7; - unsigned int one : 1; - } bNotify1; - uint8_t StatusByte; -} usbtmc_read_stb_interrupt_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c deleted file mode 100644 index 4e320a77..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Nathan Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This library is not fully reentrant, though it is reentrant from the view - * of either the application layer or the USB stack. Due to its locking, - * it is not safe to call its functions from interrupts. - * - * The one exception is that its functions may not be called from the application - * until the USB stack is initialized. This should not be a problem since the - * device shouldn't be sending messages until it receives a request from the - * host. - */ - - -/* - * In the case of single-CPU "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", - * the mutex structure's main effect is to disable the USB interrupts. - * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. - */ - -//Limitations: -// "vendor-specific" commands are not handled. -// Dealing with "termchar" must be handled by the application layer, -// though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're not permitted -// in USB488, anyway. - -/* Supported: - * - * Notification pulse - * Trigger - * Read status byte (both by interrupt endpoint and control message) - * - */ - - -// TODO: -// USBTMC 3.2.2 error conditions not strictly followed -// No local lock-out, REN, or GTL. -// Clear message available status byte at the correct time? (488 4.3.1.3) -// Ability to defer status byte transmission -// Transmission of status byte in response to USB488 SRQ condition - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_USBTMC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "usbtmc_device.h" - -#ifdef xDEBUG -#include "uart_util.h" -tu_static char logMsg[150]; -#endif - -// Buffer size must be an exact multiple of the max packet size for both -// bulk (up to 64 bytes for FS, 512 bytes for HS). In addation, this driver -// imposes a minimum buffer size of 32 bytes. -#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* - * The state machine does not allow simultaneous reading and writing. This is - * consistent with USBTMC. - */ - -typedef enum -{ - STATE_CLOSED, // Endpoints have not yet been opened since USB reset - STATE_NAK, // Bulk-out endpoint is in NAK state. - STATE_IDLE, // Bulk-out endpoint is waiting for CMD. - STATE_RCV, // Bulk-out is receiving DEV_DEP message - STATE_TX_REQUESTED, - STATE_TX_INITIATED, - STATE_TX_SHORTED, - STATE_CLEARING, - STATE_ABORTING_BULK_IN, - STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted - STATE_ABORTING_BULK_OUT, - STATE_NUM_STATES -} usbtmcd_state_enum; - -#if (CFG_TUD_USBTMC_ENABLE_488) - typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; -#else - typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; -#endif - - -typedef struct -{ - volatile usbtmcd_state_enum state; - - uint8_t itf_id; - uint8_t rhport; - uint8_t ep_bulk_in; - uint8_t ep_bulk_out; - uint8_t ep_int_in; - // IN buffer is only used for first packet, not the remainder - // in order to deal with prepending header - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE]; - uint32_t ep_bulk_in_wMaxPacketSize; - // OUT buffer receives one packet at a time - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE]; - uint32_t ep_bulk_out_wMaxPacketSize; - - uint32_t transfer_size_remaining; // also used for requested length for bulk IN. - uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) - - uint8_t lastBulkOutTag; // used for aborts (mostly) - uint8_t lastBulkInTag; // used for aborts (mostly) - - uint8_t const * devInBuffer; // pointer to application-layer used for transmissions - - usbtmc_capabilities_specific_t const * capabilities; -} usbtmc_interface_state_t; - -CFG_TUSB_MEM_SECTION tu_static usbtmc_interface_state_t usbtmc_state = -{ - .itf_id = 0xFF, -}; - -// We need all headers to fit in a single packet in this implementation, 32 bytes will fit all standard USBTMC headers -TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u,"USBTMC dev buffer size too small"); - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); - -#ifndef NDEBUG -tu_static uint8_t termChar; -#endif - -tu_static uint8_t termCharRequested = false; - -#if OSAL_MUTEX_REQUIRED -static OSAL_MUTEX_DEF(usbtmcLockBuffer); -#endif -osal_mutex_t usbtmcLock; - -// Our own private lock, mostly for the state variable. -#define criticalEnter() do { (void) osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) -#define criticalLeave() do { (void) osal_mutex_unlock(usbtmcLock); } while (0) - -bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) -{ - bool ret = true; - criticalEnter(); - usbtmcd_state_enum oldState = usbtmc_state.state; - if (oldState == expectedState) - { - usbtmc_state.state = newState; - } - else - { - ret = false; - } - criticalLeave(); - return ret; -} - -// called from app -// We keep a reference to the buffer, so it MUST not change until the app is -// notified that the transfer is complete. -// length of data is specified in the hdr. - -// We can't just send the whole thing at once because we need to concatanate the -// header with the data. -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, - bool usingTermChar) -{ - const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); - -#ifndef NDEBUG - TU_ASSERT(len > 0u); - TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); - TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); - if(usingTermChar) - { - TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); - } -#endif - - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - tu_varclr(hdr); - hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; - hdr->header.bTag = usbtmc_state.lastBulkInTag; - hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); - hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = endOfMessage; - hdr->bmTransferAttributes.UsingTermChar = usingTermChar; - - // Copy in the header - const size_t headerLen = sizeof(*hdr); - const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? - len : (txBufLen - headerLen); - const size_t packetLen = headerLen + dataLen; - - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); - usbtmc_state.transfer_size_remaining = len - dataLen; - usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); - - bool stateChanged = - atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); - TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); - return true; -} - -void usbtmcd_init_cb(void) -{ - usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); -#ifndef NDEBUG -# if CFG_TUD_USBTMC_ENABLE_488 - if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); - } - // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); -# endif - if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); - } -#endif - - usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); -} - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void)rhport; - - uint16_t drv_len; - uint8_t const * p_desc; - uint8_t found_endpoints = 0; - - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); - -#ifndef NDEBUG - // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); -#endif - - TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); - - // Interface - drv_len = 0u; - p_desc = (uint8_t const *) itf_desc; - - usbtmc_state.itf_id = itf_desc->bInterfaceNumber; - usbtmc_state.rhport = rhport; - - while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) - { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; - switch(ep_desc->bmAttributes.xfer) { - case TUSB_XFER_BULK: - // Ensure buffer is an exact multiple of the maxPacketSize - TU_ASSERT((USBTMCD_BUFFER_SIZE % tu_edpt_packet_size(ep_desc)) == 0, 0); - if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) - { - usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; - usbtmc_state.ep_bulk_in_wMaxPacketSize = tu_edpt_packet_size(ep_desc); - } else { - usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; - usbtmc_state.ep_bulk_out_wMaxPacketSize = tu_edpt_packet_size(ep_desc); - } - - break; - case TUSB_XFER_INTERRUPT: -#ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); -#endif - usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; - break; - default: - TU_ASSERT(false, 0); - } - TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); - found_endpoints++; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // bulk endpoints are required, but interrupt IN is optional -#ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); - if (itf_desc->bNumEndpoints == 2) - { - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); - } - else if (itf_desc->bNumEndpoints == 3) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#if (CFG_TUD_USBTMC_ENABLE_488) - if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || - usbtmc_state.capabilities->bmDevCapabilities488.SR1) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#endif -#endif - atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_open_cb(itf_desc->iInterface); - - return drv_len; -} -// Tell USBTMC class to set its bulk-in EP to ACK so that it can -// receive USBTMC commands. -// Returns false if it was already in an ACK state or is busy -// processing a command (such as a clear). Returns true if it was -// in the NAK state and successfully transitioned to the ACK wait -// state. -bool tud_usbtmc_start_bus_read() -{ - usbtmcd_state_enum oldState = usbtmc_state.state; - switch(oldState) - { - // These may transition to IDLE - case STATE_NAK: - case STATE_ABORTING_BULK_IN_ABORTED: - TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); - break; - // When receiving, let it remain receiving - case STATE_RCV: - break; - default: - return false; - } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize)); - return true; -} - -void usbtmcd_reset_cb(uint8_t rhport) -{ - (void)rhport; - usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); - - criticalEnter(); - tu_varclr(&usbtmc_state); - usbtmc_state.capabilities = capabilities; - usbtmc_state.itf_id = 0xFFu; - criticalLeave(); -} - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); - usbtmc_state.transfer_size_sent = 0u; - - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); - - TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; - return true; -} - -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(usbtmc_state.state == STATE_RCV,true); - - bool shortPacket = (packetLen < usbtmc_state.ep_bulk_out_wMaxPacketSize); - - // Packet is to be considered complete when we get enough data or at a short packet. - bool atEnd = false; - if(len >= usbtmc_state.transfer_size_remaining || shortPacket) - { - atEnd = true; - TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); - } - - len = tu_min32(len, usbtmc_state.transfer_size_remaining); - - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - - // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) - { - // TODO: Go to an error state upon failure other than just stalling the EP? - return false; - } - - - return true; -} - -static bool handle_devMsgIn(void *data, size_t len) -{ - TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); - usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); - TU_VERIFY(stateChanged); - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - - termCharRequested = msg->bmTransferAttributes.TermCharEnabled; - -#ifndef NDEBUG - termChar = msg->TermChar; -#endif - - if(termCharRequested) - TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - - TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); - return true; -} - -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - TU_VERIFY(result == XFER_RESULT_SUCCESS); - //uart_tx_str_sync("TMC XFER CB\r\n"); - if(usbtmc_state.state == STATE_CLEARING) { - return true; /* I think we can ignore everything here */ - } - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - usbtmc_msg_generic_t *msg = NULL; - - switch(usbtmc_state.state) - { - case STATE_IDLE: - { - TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); - uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); - TU_VERIFY(msg->header.bTag == invInvTag); - TU_VERIFY(msg->header.bTag != 0x00); - - switch(msg->header.MsgID) { - case USBTMC_MSGID_DEV_DEP_MSG_OUT: - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - break; - - case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; - -#if (CFG_TUD_USBTMC_ENABLE_488) - case USBTMC_MSGID_USB488_TRIGGER: - // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); - - break; -#endif - case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: - case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - default: - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - return true; - } - case STATE_RCV: - if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - return true; - - case STATE_ABORTING_BULK_OUT: - // Should be stalled by now, shouldn't have received a packet. - return false; - - case STATE_TX_REQUESTED: - case STATE_TX_INITIATED: - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_IN_SHORTED: - case STATE_ABORTING_BULK_IN_ABORTED: - default: - return false; - } - } - else if(ep_addr == usbtmc_state.ep_bulk_in) - { - switch(usbtmc_state.state) { - case STATE_TX_SHORTED: - TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); - break; - - case STATE_TX_INITIATED: - if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf)) - { - // FIXME! This removes const below! - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, - (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); - if(((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0 )) - { - usbtmc_state.state = STATE_TX_SHORTED; - } - } - return true; - - case STATE_ABORTING_BULK_IN: - // need to send short packet (ZLP?) - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - return true; - - case STATE_ABORTING_BULK_IN_SHORTED: - /* Done. :)*/ - usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; - - default: - TU_ASSERT(false); - } - } - else if (ep_addr == usbtmc_state.ep_int_in) { - // Good? - return true; - } - return false; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA and ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_TUD_USBTMC_ENABLE_488) - uint8_t bTag; -#endif - - if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && - (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && - (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && - (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) - { - uint32_t ep_addr = (request->wIndex); - - // At this point, a transfer MAY be in progress. Based on USB spec, when clearing bulk EP HALT, - // the EP transfer buffer needs to be cleared and DTOG needs to be reset, even if - // the EP is not halted. The only USBD API interface to do this is to stall and then un-stall the EP. - if(ep_addr == usbtmc_state.ep_bulk_out) - { - criticalEnter(); - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us - criticalLeave(); - tud_usbtmc_bulkOut_clearFeature_cb(); - } - else if (ep_addr == usbtmc_state.ep_bulk_in) - { - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - tud_usbtmc_bulkIn_clearFeature_cb(); - } - else if ((usbtmc_state.ep_int_in != 0) && (ep_addr == usbtmc_state.ep_int_in)) - { - // Clearing interrupt in EP - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - } - else - { - return false; - } - return true; - } - - // Otherwise, we only handle class requests. - if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) - { - return false; - } - - // Verification that we own the interface is unneeded since it's been routed to us specifically. - - switch(request->bRequest) - { - // USBTMC required requests - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkOutTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - - // wValue is the requested bTag to abort - if(usbtmc_state.state != STATE_RCV) - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = STATE_ABORTING_BULK_OUT; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - { - usbtmc_check_abort_bulk_rsp_t rsp = { - .USBTMC_status = USBTMC_STATUS_SUCCESS, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkInTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); - // wValue is the requested bTag to abort - if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0u; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % usbtmc_state.ep_bulk_in_wMaxPacketSize) == 0) ? - STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; - criticalLeave(); - if(usbtmc_state.transfer_size_sent == 0) - { - // Send short packet, nothing is in the buffer yet - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - } - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); - } - else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) - { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 8u); - - usbtmc_check_abort_bulk_rsp_t rsp = - { - .USBTMC_status = USBTMC_STATUS_FAILED, - .bmAbortBulkIn = - { - .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) - }, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, - }; - TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); - criticalEnter(); - switch(usbtmc_state.state) - { - case STATE_ABORTING_BULK_IN_ABORTED: - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.state = STATE_IDLE; - break; - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: - rsp.USBTMC_status = USBTMC_STATUS_PENDING; - break; - default: - break; - } - criticalLeave(); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - - return true; - } - - case USBTMC_bREQUEST_INITIATE_CLEAR: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the - // control endpoint response shown in Table 31, and clear all input buffers and output buffers. - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - usbtmc_state.transfer_size_remaining = 0; - criticalEnter(); - usbtmc_state.state = STATE_CLEARING; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); - return true; - } - - case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - - if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) - { - // Stuff stuck in TX buffer? - clearStatusRsp.bmClear.BulkInFifoBytes = 1; - clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; - } - else - { - // Let app check if it's clear - TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); - } - if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) - { - criticalEnter(); - usbtmc_state.state = STATE_IDLE; - criticalLeave(); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); - return true; - } - - case USBTMC_bREQUEST_GET_CAPABILITIES: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); - return true; - } - // USBTMC Optional Requests - - case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); - return true; - } -#if (CFG_TUD_USBTMC_ENABLE_488) - - // USB488 required requests - case USB488_bREQUEST_READ_STATUS_BYTE: - { - usbtmc_read_stb_rsp_488_t rsp; - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero (USB488v1.0 Table 11) - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) - { - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. Must be 0x00 (USB488v1.0 4.3.1.2) - if(usbd_edpt_busy(rhport, usbtmc_state.ep_int_in)) - { - rsp.USBTMC_status = USB488_STATUS_INTERRUPT_IN_BUSY; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_read_stb_interrupt_488_t intMsg = - { - .bNotify1 = { - .one = 1, - .bTag = bTag & 0x7Fu, - }, - .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) - }; - // Must be queued before control request response sent (USB488v1.0 4.3.1.2) - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); - } - } - else - { - rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; - } - // USB488 optional requests - case USB488_bREQUEST_REN_CONTROL: - case USB488_bREQUEST_GO_TO_LOCAL: - case USB488_bREQUEST_LOCAL_LOCKOUT: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - return false; - } -#endif - - default: - return false; - } -} - -#endif /* CFG_TUD_TSMC */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h deleted file mode 100644 index c1298ddb..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/usbtmc/usbtmc_device.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ -#define CLASS_USBTMC_USBTMC_DEVICE_H_ - -#include "usbtmc.h" - -// Enable 488 mode by default -#if !defined(CFG_TUD_USBTMC_ENABLE_488) -#define CFG_TUD_USBTMC_ENABLE_488 (1) -#endif - -/*********************************************** - * Functions to be implemented by the class implementation - */ - -// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_open_cb -// * tud_usbtmc_msg_data_cb -// * tud_usbtmc_msgBulkIn_complete_cb -// * tud_usbtmc_msg_trigger_cb -// * (successful) tud_usbtmc_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_bulkOut_clearFeature_cb - -#if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); -#else -usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); -#endif - -void tud_usbtmc_open_cb(uint8_t interface_id); - -bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); -// transfer_complete does not imply that a message is complete. -bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_msgBulkIn_complete_cb(void); -void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); - -bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); - -// Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); - -#if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); -#endif - -/******************************************* - * Called from app - * - * We keep a reference to the buffer, so it MUST not change until the app is - * notified that the transfer is complete. - ******************************************/ - -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, bool usingTermChar); - -bool tud_usbtmc_start_bus_read(void); - - -/* "callbacks" from USB device core */ - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); - -/************************************************************ - * USBTMC Descriptor Templates - *************************************************************/ - - -#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.c deleted file mode 100644 index 93596ee3..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_VENDOR) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "vendor_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; -} vendord_interface_t; - -CFG_TUSB_MEM_SECTION tu_static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; - -#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) - - -bool tud_vendor_n_mounted (uint8_t itf) -{ - return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; -} - -uint32_t tud_vendor_n_available (uint8_t itf) -{ - return tu_fifo_count(&_vendord_itf[itf].rx_ff); -} - -bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) -{ - return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); -} - -//--------------------------------------------------------------------+ -// Read API -//--------------------------------------------------------------------+ -static void _prep_out_transaction (vendord_interface_t* p_itf) -{ - uint8_t const rhport = 0; - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_itf->ep_out), ); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); - if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) - { - usbd_edpt_xfer(rhport, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); - } - else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_itf->ep_out); - } -} - -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, (uint16_t) bufsize); - _prep_out_transaction(p_itf); - return num_read; -} - -void tud_vendor_n_read_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - tu_fifo_clear(&p_itf->rx_ff); - _prep_out_transaction(p_itf); -} - -//--------------------------------------------------------------------+ -// Write API -//--------------------------------------------------------------------+ -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, (uint16_t) bufsize); - - // flush if queue more than packet size - if (tu_fifo_count(&p_itf->tx_ff) >= CFG_TUD_VENDOR_EPSIZE) { - tud_vendor_n_write_flush(itf); - } - return ret; -} - -uint32_t tud_vendor_n_write_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); - - // No data to send - if ( !tu_fifo_count(&p_itf->tx_ff) ) return 0; - - uint8_t const rhport = 0; - - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_itf->ep_in), 0 ); - - // Pull data from FIFO - uint16_t const count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, sizeof(p_itf->epin_buf)); - - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_itf->ep_in, p_itf->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_itf->ep_in); - return 0; - } -} - -uint32_t tud_vendor_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_vendord_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void vendord_init(void) -{ - tu_memclr(_vendord_itf, sizeof(_vendord_itf)); - - for(uint8_t i=0; irx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); -#endif - } -} - -void vendord_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_itf->tx_ff); - } -} - -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - - uint8_t const * p_desc = tu_desc_next(desc_itf); - uint8_t const * desc_end = p_desc + max_len; - - // Find available interface - vendord_interface_t* p_vendor = NULL; - for(uint8_t i=0; iitf_num = desc_itf->bInterfaceNumber; - if (desc_itf->bNumEndpoints) - { - // skip non-endpoint descriptors - while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) - { - p_desc = tu_desc_next(p_desc); - } - - // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); - - p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - // Prepare for incoming data - if ( p_vendor->ep_out ) - { - _prep_out_transaction(p_vendor); - } - - if ( p_vendor->ep_in ) tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); - } - - return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf); -} - -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - uint8_t itf = 0; - vendord_interface_t* p_itf = _vendord_itf; - - for ( ; ; itf++, p_itf++) - { - if (itf >= TU_ARRAY_SIZE(_vendord_itf)) return false; - - if ( ( ep_addr == p_itf->ep_out ) || ( ep_addr == p_itf->ep_in ) ) break; - } - - if ( ep_addr == p_itf->ep_out ) - { - // Receive new data - tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, (uint16_t) xferred_bytes); - - // Invoked callback if any - if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); - - _prep_out_transaction(p_itf); - } - else if ( ep_addr == p_itf->ep_in ) - { - if (tud_vendor_tx_cb) tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes); - // Send complete, try to send more if possible - tud_vendor_n_write_flush(itf); - } - - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.h deleted file mode 100644 index d239406b..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_device.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ - -#include "common/tusb_common.h" - -#ifndef CFG_TUD_VENDOR_EPSIZE -#define CFG_TUD_VENDOR_EPSIZE 64 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -//--------------------------------------------------------------------+ -bool tud_vendor_n_mounted (uint8_t itf); - -uint32_t tud_vendor_n_available (uint8_t itf); -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); -void tud_vendor_n_read_flush (uint8_t itf); - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -uint32_t tud_vendor_n_write_flush (uint8_t itf); -uint32_t tud_vendor_n_write_available (uint8_t itf); - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); - -// backward compatible -#define tud_vendor_n_flush(itf) tud_vendor_n_write_flush(itf) - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_vendor_mounted (void); -static inline uint32_t tud_vendor_available (void); -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (uint8_t* ui8); -static inline void tud_vendor_read_flush (void); -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_vendor_write_str (char const* str); -static inline uint32_t tud_vendor_write_available (void); -static inline uint32_t tud_vendor_write_flush (void); - -// backward compatible -#define tud_vendor_flush() tud_vendor_write_flush() - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); -// Invoked when last rx transfer finished -TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str) -{ - return tud_vendor_n_write(itf, str, strlen(str)); -} - -static inline bool tud_vendor_mounted (void) -{ - return tud_vendor_n_mounted(0); -} - -static inline uint32_t tud_vendor_available (void) -{ - return tud_vendor_n_available(0); -} - -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) -{ - return tud_vendor_n_read(0, buffer, bufsize); -} - -static inline bool tud_vendor_peek (uint8_t* ui8) -{ - return tud_vendor_n_peek(0, ui8); -} - -static inline void tud_vendor_read_flush(void) -{ - tud_vendor_n_read_flush(0); -} - -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) -{ - return tud_vendor_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_vendor_write_flush (void) -{ - return tud_vendor_n_write_flush(0); -} - -static inline uint32_t tud_vendor_write_str (char const* str) -{ - return tud_vendor_n_write_str(0, str); -} - -static inline uint32_t tud_vendor_write_available (void) -{ - return tud_vendor_n_write_available(0); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_DEVICE_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.c b/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.c deleted file mode 100644 index e66c5007..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_VENDOR) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "host/usbh.h" -#include "vendor_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; - -static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) - { - return TUSB_ERROR_DEVICE_NOT_READY; - } - - TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); - - return TUSB_ERROR_NONE; -} -//--------------------------------------------------------------------+ -// APPLICATION API (need to check parameters) -//--------------------------------------------------------------------+ -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS API -//--------------------------------------------------------------------+ -void cush_init(void) -{ - tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); -} - -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) -{ - // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; - p_desc = tu_desc_next(p_desc); - - //------------- Bulk Endpoints Descriptor -------------// - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); - - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? - &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); - TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - - p_desc = tu_desc_next(p_desc); - } - - (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return TUSB_ERROR_NONE; -} - -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) -{ - -} - -void cush_close(uint8_t dev_addr) -{ - tusb_error_t err1, err2; - custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; - - // TODO re-consider to check pipe valid before calling pipe_close - if( pipehandle_is_valid( p_interface->pipe_in ) ) - { - err1 = hcd_pipe_close( p_interface->pipe_in ); - } - - if ( pipehandle_is_valid( p_interface->pipe_out ) ) - { - err2 = hcd_pipe_close( p_interface->pipe_out ); - } - - tu_memclr(p_interface, sizeof(custom_interface_info_t)); - - TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.h b/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.h deleted file mode 100644 index acfebe7a..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/vendor/vendor_host.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct { - pipe_handle_t pipe_in; - pipe_handle_t pipe_out; -}custom_interface_info_t; - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) -{ - (void) vendor_id; // TODO check this later - (void) product_id; -// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0; - return false; -} - -bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); -bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cush_init(void); -bool cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); -void cush_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_HOST_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/video/video.h b/test-devices/loopback-stm32/lib/tinyusb/class/video/video.h deleted file mode 100644 index c0088c4f..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/video/video.h +++ /dev/null @@ -1,559 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_H_ -#define TUSB_VIDEO_H_ - -#include "common/tusb_common.h" - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, - VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) - VIDEO_COLOR_PRIMARIES_BT470_2M, - VIDEO_COLOR_PRIMARIES_BT470_2BG, - VIDEO_COLOR_PRIMARIES_SMPTE170M, - VIDEO_COLOR_PRIMARIES_SMPTE240M, -} video_color_primaries_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, - VIDEO_COLOR_XFER_CH_BT709, // default - VIDEO_COLOR_XFER_CH_BT470_2M, - VIDEO_COLOR_XFER_CH_BT470_2BG, - VIDEO_COLOR_XFER_CH_SMPTE170M, - VIDEO_COLOR_XFER_CH_SMPTE240M, - VIDEO_COLOR_XFER_CH_LINEAR, - VIDEO_COLOR_XFER_CH_SRGB, -} video_color_transfer_characteristics_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_COEF_UNDEFINED = 0x00, - VIDEO_COLOR_COEF_BT709, - VIDEO_COLOR_COEF_FCC, - VIDEO_COLOR_COEF_BT470_2BG, - VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default - VIDEO_COLOR_COEF_SMPTE240M, -} video_color_matrix_coefficients_t; - -/* 4.2.1.2 Request Error Code Control */ -typedef enum { - VIDEO_ERROR_NONE = 0, /* The request succeeded. */ - VIDEO_ERROR_NOT_READY, - VIDEO_ERROR_WRONG_STATE, - VIDEO_ERROR_POWER, - VIDEO_ERROR_OUT_OF_RANGE, - VIDEO_ERROR_INVALID_UNIT, - VIDEO_ERROR_INVALID_CONTROL, - VIDEO_ERROR_INVALID_REQUEST, - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, - VIDEO_ERROR_UNKNOWN = 0xFF, -} video_error_code_t; - -/* A.2 Interface Subclass */ -typedef enum { - VIDEO_SUBCLASS_UNDEFINED = 0x00, - VIDEO_SUBCLASS_CONTROL, - VIDEO_SUBCLASS_STREAMING, - VIDEO_SUBCLASS_INTERFACE_COLLECTION, -} video_subclass_type_t; - -/* A.3 Interface Protocol */ -typedef enum { - VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, - VIDEO_ITF_PROTOCOL_15, -} video_interface_protocol_code_t; - -/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VC_UNDEFINED = 0x00, - VIDEO_CS_ITF_VC_HEADER, - VIDEO_CS_ITF_VC_INPUT_TERMINAL, - VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - VIDEO_CS_ITF_VC_SELECTOR_UNIT, - VIDEO_CS_ITF_VC_PROCESSING_UNIT, - VIDEO_CS_ITF_VC_EXTENSION_UNIT, - VIDEO_CS_ITF_VC_ENCODING_UNIT, - VIDEO_CS_ITF_VC_MAX, -} video_cs_vc_interface_subtype_t; - -/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VS_UNDEFINED = 0x00, - VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, - VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, - VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, - VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, - VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, - VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, - VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, - VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, - VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, - VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, - VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, - VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, - VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, - VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, - VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, - VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, - VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, - VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, - VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, -} video_cs_vs_interface_subtype_t; - -/* A.7. Class-Specific Endpoint Descriptor Subtypes */ -typedef enum { - VIDEO_CS_EP_UNDEFINED = 0x00, - VIDEO_CS_EP_GENERAL, - VIDEO_CS_EP_ENDPOINT, - VIDEO_CS_EP_INTERRUPT -} video_cs_ep_subtype_t; - -/* A.8 Class-Specific Request Codes */ -typedef enum { - VIDEO_REQUEST_UNDEFINED = 0x00, - VIDEO_REQUEST_SET_CUR = 0x01, - VIDEO_REQUEST_SET_CUR_ALL = 0x11, - VIDEO_REQUEST_GET_CUR = 0x81, - VIDEO_REQUEST_GET_MIN = 0x82, - VIDEO_REQUEST_GET_MAX = 0x83, - VIDEO_REQUEST_GET_RES = 0x84, - VIDEO_REQUEST_GET_LEN = 0x85, - VIDEO_REQUEST_GET_INFO = 0x86, - VIDEO_REQUEST_GET_DEF = 0x87, - VIDEO_REQUEST_GET_CUR_ALL = 0x91, - VIDEO_REQUEST_GET_MIN_ALL = 0x92, - VIDEO_REQUEST_GET_MAX_ALL = 0x93, - VIDEO_REQUEST_GET_RES_ALL = 0x94, - VIDEO_REQUEST_GET_DEF_ALL = 0x97 -} video_control_request_t; - -/* A.9.1 VideoControl Interface Control Selectors */ -typedef enum { - VIDEO_VC_CTL_UNDEFINED = 0x00, - VIDEO_VC_CTL_VIDEO_POWER_MODE, - VIDEO_VC_CTL_REQUEST_ERROR_CODE, -} video_interface_control_selector_t; - -/* A.9.8 VideoStreaming Interface Control Selectors */ -typedef enum { - VIDEO_VS_CTL_UNDEFINED = 0x00, - VIDEO_VS_CTL_PROBE, - VIDEO_VS_CTL_COMMIT, - VIDEO_VS_CTL_STILL_PROBE, - VIDEO_VS_CTL_STILL_COMMIT, - VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, - VIDEO_VS_CTL_STREAM_ERROR_CODE, - VIDEO_VS_CTL_GENERATE_KEY_FRAME, - VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, - VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, -} video_interface_streaming_selector_t; - -/* B. Terminal Types */ -typedef enum { - // Terminal - VIDEO_TT_VENDOR_SPECIFIC = 0x0100, - VIDEO_TT_STREAMING = 0x0101, - - // Input - VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, - VIDEO_ITT_CAMERA = 0x0201, - VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, - - // Output - VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, - VIDEO_OTT_DISPLAY = 0x0301, - VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, - - // External - VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, - VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, - VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, - VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, -} video_terminal_type_t; - -//--------------------------------------------------------------------+ -// Descriptors -//--------------------------------------------------------------------+ - -/* 2.3.4.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; - -/* 2.4.3.3 */ -typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; - -/* 3.9.2.1 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; - -/* 3.9.2.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - union { - struct { - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; - } input; - struct { - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; - } output; - }; -} tusb_desc_cs_video_stm_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t bmFlags; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_mjpeg_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint8_t bFormatType; -} tusb_desc_cs_video_fmt_dv_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; - uint8_t bVaribaleSize; -} tusb_desc_cs_video_fmt_frame_based_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwBytesPerLine; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_frame_based_t; - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ - -/* 4.3.1.1 */ -typedef struct TU_ATTR_PACKED { - union { - uint8_t bmHint; - struct TU_ATTR_PACKED { - uint16_t dwFrameInterval: 1; - uint16_t wKeyFrameRatel : 1; - uint16_t wPFrameRate : 1; - uint16_t wCompQuality : 1; - uint16_t wCompWindowSize: 1; - uint16_t : 0; - } Hint; - }; - uint8_t bFormatIndex; - uint8_t bFrameIndex; - uint32_t dwFrameInterval; - uint16_t wKeyFrameRate; - uint16_t wPFrameRate; - uint16_t wCompQuality; - uint16_t wCompWindowSize; - uint16_t wDelay; - uint32_t dwMaxVideoFrameSize; - uint32_t dwMaxPayloadTransferSize; - uint32_t dwClockFrequency; - union { - uint8_t bmFramingInfo; - struct TU_ATTR_PACKED { - uint8_t FrameID : 1; - uint8_t EndOfFrame: 1; - uint8_t EndOfSlice: 1; - uint8_t : 0; - } FramingInfo; - }; - uint8_t bPreferedVersion; - uint8_t bMinVersion; - uint8_t bMaxVersion; - uint8_t bUsage; - uint8_t bBitDepthLuma; - uint8_t bmSettings; - uint8_t bMaxNumberOfRefFramesPlus1; - uint16_t bmRateControlModes; - uint64_t bmLayoutPerStream; -} video_probe_and_commit_control_t; - -TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); - -#define TUD_VIDEO_DESC_IAD_LEN 8 -#define TUD_VIDEO_DESC_STD_VC_LEN 9 -#define TUD_VIDEO_DESC_CS_VC_LEN 12 -#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 -#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 -#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 -#define TUD_VIDEO_DESC_STD_VS_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 -#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 -#define TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN 11 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 - -/* 2.2 compression formats */ -#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 - -#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ - _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ - VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx - -#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ - TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ - _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.7.2 */ -#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ - TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ - U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ - U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ - -/* 3.7.2.1 */ -#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ - TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _stridx - -/* 3.7.2.2 */ -#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ - TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx - -/* 3.7.2.3 */ -#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ - U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ - TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) - -/* 3.9.1 */ -#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ - TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ - _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.9.2.1 */ -#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ - TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.2 */ -#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ - TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Uncompressed 3.1.1 */ -#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 - -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ - _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ - _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ - _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp - -/* Uncompressed 3.1.2 Table 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Uncompressed 3.1.2 Table 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Motion-JPEG 3.1.1 Table 3-1 */ -#define TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(_fmtidx, _numfrmdesc, _fixed_sz, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_MJPEG, \ - _fmtidx, _numfrmdesc, _fixed_sz, _frmidx, _asrx, _asry, _interlace, _cp - -/* Motion-JPEG 3.1.1 Table 3-2 and 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_MJPEG, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Motion-JPEG 3.1.1 Table 3-2 and 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_VS_INTERFACE_FRAME_MJPEG, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.6 */ -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ - TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ - _color, _trns, _mat - -/* 3.10.1.1 */ -#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS),\ - U16_TO_U8S_LE(_epsize), _ep_interval - -/* 3.10.1.2 */ -#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.c b/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.c deleted file mode 100644 index d6e98602..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.c +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUD_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "video_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; -} tusb_desc_vc_itf_t; - -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_vs_itf_t; - -typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_video_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bEntityId; -} tusb_desc_cs_video_entity_itf_t; - -typedef union { - struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - }; - tusb_desc_cs_video_fmt_uncompressed_t uncompressed; - tusb_desc_cs_video_fmt_mjpeg_t mjpeg; - tusb_desc_cs_video_fmt_frame_based_t frame_based; -} tusb_desc_cs_video_fmt_t; - -typedef union { - struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - }; - tusb_desc_cs_video_frm_uncompressed_t uncompressed; - tusb_desc_cs_video_frm_mjpeg_t mjpeg; - tusb_desc_cs_video_frm_frame_based_t frame_based; -} tusb_desc_cs_video_frm_t; - -/* video streaming interface */ -typedef struct TU_ATTR_PACKED { - uint8_t index_vc; /* index of bound video control interface */ - uint8_t index_vs; /* index from the video control interface */ - struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ - uint16_t end; /* Offset of the end of video streaming interface descriptor */ - uint16_t cur; /* Offset of the current settings */ - uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ - } desc; - uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ - uint32_t bufsize; /* frame buffer size */ - uint32_t offset; /* offset for the next payload transfer */ - uint32_t max_payload_transfer_size; - uint8_t error_code;/* error code */ - /*------------- From this point, data is not cleared by bus reset -------------*/ - CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ -} videod_streaming_interface_t; - -/* video control interface */ -typedef struct TU_ATTR_PACKED { - uint8_t const *beg; /* The head of the first video control interface descriptor */ - uint16_t len; /* Byte length of the descriptors */ - uint16_t cur; /* offset for current video control interface */ - uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ - uint8_t error_code; /* error code */ - uint8_t power_mode; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ - -} videod_interface_t; - -#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION tu_static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; -CFG_TUSB_MEM_SECTION tu_static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; - -tu_static uint8_t const _cap_get = 0x1u; /* support for GET */ -tu_static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ - -/** Get interface number from the interface descriptor - * - * @param[in] desc interface descriptor - * - * @return bInterfaceNumber */ -static inline uint8_t _desc_itfnum(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get endpoint address from the endpoint descriptor - * - * @param[in] desc endpoint descriptor - * - * @return bEndpointAddress */ -static inline uint8_t _desc_ep_addr(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get instance of streaming interface - * - * @param[in] ctl_idx instance number of video control - * @param[in] stm_idx index number of streaming interface - * - * @return instance */ -static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; - videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; - return stm; -} - -static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) -{ - return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); -} - -static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) -{ - if (!self->desc.cur) return NULL; - uint8_t const *desc = _videod_itf[self->index_vc].beg; - return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); -} - -/** Find the first descriptor of a given type - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) -{ - void const *cur = beg; - while ((cur < end) && (desc_type != tu_desc_type(cur))) { - cur = tu_desc_next(cur); - } - return cur; -} - -/** Find the first descriptor specified by the arguments - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type - * @param[in] element_0 The target element following the desc_type - * @param[in] element_1 The target element following the element_0 - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_3(void const *beg, void const *end, - uint_fast8_t desc_type, - uint_fast8_t element_0, - uint_fast8_t element_1) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { - uint8_t const *p = (uint8_t const *)cur; - if ((p[2] == element_0) && (p[3] == element_1)) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the next interface descriptor which has another interface number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _next_desc_itf(void const *beg, void const *end) -{ - void const *cur = beg; - uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; - while ((cur < end) && - (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { - cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); - } - return cur; -} - -/** Find the first interface descriptor with the specified interface number and alternate setting number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] itfnum The target interface number. - * @param[in] altnum The target alternate setting number. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static inline uint8_t const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) -{ - return (uint8_t const*) _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); -} - -/** Find the first endpoint descriptor belonging to the current interface descriptor. - * - * The search range is from `beg` to `end` or the next interface descriptor. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for endpoint descriptor. - * @retval end did not found endpoint descriptor */ -static void const* _find_desc_ep(void const *beg, void const *end) -{ - for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { - uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; - } - return end; -} - -/** Return the end of the video control descriptor. */ -static inline void const* _end_of_control_descriptor(void const *desc) -{ - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)desc; - return ((uint8_t const*) desc) + vc->std.bLength + tu_le16toh(vc->ctl.wTotalLength); -} - -/** Find the first entity descriptor with the entity ID - * specified by the argument belonging to the current video control descriptor. - * - * @param[in] desc The video control interface descriptor. - * @param[in] entityid The target entity id. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) -{ - void const *end = _end_of_control_descriptor(desc); - for (void const *cur = desc; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; - if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype - && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) - && itf->bEntityId == entityid) { - return itf; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the end of the video streaming descriptor. */ -static inline void const* _end_of_streaming_descriptor(void const *desc) -{ - tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; - return ((uint8_t const*) desc) + vs->std.bLength + tu_le16toh(vs->stm.wTotalLength); -} - -/** Find the first format descriptor with the specified format number. */ -static inline void const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - uint8_t const *p = (uint8_t const *)cur; - uint_fast8_t fmt = p[2]; - if ((fmt == VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED || - fmt == VIDEO_CS_ITF_VS_FORMAT_MJPEG || - fmt == VIDEO_CS_ITF_VS_FORMAT_DV || - fmt == VIDEO_CS_ITF_VS_FRAME_FRAME_BASED) && - fmtnum == p[3]) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Find the first frame descriptor with the specified format number. */ -static inline void const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - uint8_t const *p = (uint8_t const *)cur; - uint_fast8_t frm = p[2]; - if ((frm == VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED || - frm == VIDEO_CS_ITF_VS_FRAME_MJPEG || - frm == VIDEO_CS_ITF_VS_FRAME_FRAME_BASED) && - frmnum == p[3]) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Set uniquely determined values to variables that have not been set - * - * @param[in,out] param Target */ -static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, - video_probe_and_commit_control_t *param) -{ - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - uint_fast8_t fmtnum = param->bFormatIndex; - TU_ASSERT(vs && fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ - fmtnum = 1; - param->bFormatIndex = 1; - } - - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - TU_ASSERT(fmt != end); - - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - param->wCompQuality = 1; /* 1 to 10000 */ - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - break; - default: return false; - } - - uint_fast8_t frmnum = param->bFrameIndex; - TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; - frmnum = 1; - param->bFrameIndex = 1; - } - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - TU_ASSERT(frm != end); - - /* Set the parameters determined by the frame */ - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */ - break; - default: break; - } - param->dwMaxVideoFrameSize = frame_size; - } - - uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { - if ((1 < frm->uncompressed.bFrameIntervalType) || - ((0 == frm->uncompressed.bFrameIntervalType) && - (frm->uncompressed.dwFrameInterval[1] != frm->uncompressed.dwFrameInterval[0]))) { - return true; - } - interval = frm->uncompressed.dwFrameInterval[0]; - param->dwFrameInterval = interval; - } - uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); - uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) - payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; - param->dwMaxPayloadTransferSize = payload_size; - return true; -} - -/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host - * - * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF - * @param[in,out] param Target - */ -static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, - video_probe_and_commit_control_t *param) -{ - uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { - switch (request) { - case VIDEO_REQUEST_GET_MAX: - if (_get_desc_vs(stm)) - param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; - break; - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_DEF: - param->bFormatIndex = 1; - break; - default: return false; - } - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - return true; - } - - uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - TU_ASSERT(vs); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - switch (request) { - case VIDEO_REQUEST_GET_MAX: - frmnum = fmt->bNumFrameDescriptors; - break; - case VIDEO_REQUEST_GET_MIN: - frmnum = 1; - break; - case VIDEO_REQUEST_GET_DEF: - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frmnum = fmt->uncompressed.bDefaultFrameIndex; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frmnum = fmt->mjpeg.bDefaultFrameIndex; - break; - default: return false; - } - break; - default: return false; - } - param->bFrameIndex = (uint8_t)frmnum; - /* Set the parameters determined by the frame */ - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - uint_fast32_t frame_size; - switch (fmt->bDescriptorSubType) { - case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; - break; - case VIDEO_CS_ITF_VS_FORMAT_MJPEG: - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */ - break; - default: return false; - } - param->dwMaxVideoFrameSize = frame_size; - return true; - } - - if (!param->dwFrameInterval) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - TU_ASSERT(vs); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - - uint_fast32_t interval, interval_ms; - switch (request) { - case VIDEO_REQUEST_GET_MAX: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1]; - min_interval = frm->uncompressed.dwFrameInterval[0]; - interval = max_interval; - interval_ms = min_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_MIN: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1]; - min_interval = frm->uncompressed.dwFrameInterval[0]; - interval = min_interval; - interval_ms = max_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_DEF: - interval = frm->uncompressed.dwDefaultFrameInterval; - interval_ms = interval / 10000; - break; - case VIDEO_REQUEST_GET_RES: - { - uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; - if (num_intervals) { - interval = 0; - } else { - interval = frm->uncompressed.dwFrameInterval[2]; - interval_ms = interval / 10000; - } - } - break; - default: return false; - } - param->dwFrameInterval = interval; - if (!interval) { - param->dwMaxPayloadTransferSize = 0; - } else { - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - uint_fast32_t payload_size; - if (!interval_ms) { - payload_size = frame_size + 2; - } else { - payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - } - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) - payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; - param->dwMaxPayloadTransferSize = payload_size; - } - return true; - } - return true; -} - -/** Close current video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) -{ - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - - /* The next descriptor after the class-specific VC interface header descriptor. */ - void const *cur = (uint8_t const*)vc + vc->std.bLength + vc->ctl.bLength; - - /* The end of the video control interface descriptor. */ - void const *end = _end_of_control_descriptor(vc); - if (vc->std.bNumEndpoints) { - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - usbd_edpt_close(rhport, notif->bEndpointAddress); - } - self->cur = 0; - return true; -} - -/** Set the alternate setting to own video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) -{ - TU_LOG2(" open VC %d\n", altnum); - uint8_t const *beg = self->beg; - uint8_t const *end = beg + self->len; - - /* The first descriptor is a video control interface descriptor. */ - uint8_t const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_LOG2(" cur %d\n", cur - beg); - TU_VERIFY(cur < end); - - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; - TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); - /* Support for up to 2 streaming interfaces only. */ - TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); - - /* Update to point the end of the video control interface descriptor. */ - end = _end_of_control_descriptor(cur); - - /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ - cur += vc->std.bLength + vc->ctl.bLength; - TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); - /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { - /* Support for 1 endpoint only. */ - TU_VERIFY(1 == vc->std.bNumEndpoints); - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_VERIFY(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - /* Open the notification endpoint */ - TU_ASSERT(usbd_edpt_open(rhport, notif)); - } - self->cur = (uint16_t) ((uint8_t const*)vc - beg); - return true; -} - -/** Set the alternate setting to own video streaming interface. - * - * @param[in,out] stm Streaming interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) -{ - uint_fast8_t i; - TU_LOG2(" reopen VS %d\n", altnum); - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - - /* Close endpoints of previous settings. */ - for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) break; - uint8_t ep_adr = _desc_ep_addr(desc + ofs_ep); - usbd_edpt_close(rhport, ep_adr); - stm->desc.ep[i] = 0; - TU_LOG2(" close EP%02x\n", ep_adr); - } - - /* clear transfer management information */ - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - - /* Find a alternate interface */ - uint8_t const *beg = desc + stm->desc.beg; - uint8_t const *end = desc + stm->desc.end; - uint8_t const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_VERIFY(cur < end); - - uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; - TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); - stm->desc.cur = (uint16_t) (cur - desc); /* Save the offset of the new settings */ - if (!altnum) { - /* initialize streaming settings */ - stm->max_payload_transfer_size = 0; - video_probe_and_commit_control_t *param = - (video_probe_and_commit_control_t *)&stm->ep_buf; - tu_memclr(param, sizeof(*param)); - TU_LOG2(" done 0\n"); - return _update_streaming_parameters(stm, param); - } - /* Open endpoints of the new settings. */ - for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { - cur = _find_desc_ep(cur, end); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; - if (!stm->max_payload_transfer_size) { - video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; - uint_fast32_t max_size = param->dwMaxPayloadTransferSize; - if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && - (tu_edpt_packet_size(ep) < max_size)) - { - /* FS must be less than or equal to max packet size */ - return false; - } - /* Set the negotiated value */ - stm->max_payload_transfer_size = max_size; - } - TU_ASSERT(usbd_edpt_open(rhport, ep)); - stm->desc.ep[i] = (uint16_t) (cur - desc); - TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); - } - /* initialize payload header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->bHeaderLength = sizeof(*hdr); - hdr->bmHeaderInfo = 0; - - TU_LOG2(" done\n"); - return true; -} - -/** Prepare the next packet payload. */ -static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) -{ - uint_fast16_t remaining = stm->bufsize - stm->offset; - uint_fast16_t hdr_len = stm->ep_buf[0]; - uint_fast16_t pkt_len = stm->max_payload_transfer_size; - if (hdr_len + remaining < pkt_len) { - pkt_len = hdr_len + remaining; - } - uint_fast16_t data_len = pkt_len - hdr_len; - memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); - stm->offset += data_len; - remaining -= data_len; - if (!remaining) { - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->EndOfFrame = 1; - } - return hdr_len + data_len; -} - -/** Handle a standard request to the video control interface. */ -static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); - TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); - - uint8_t alt_num = vc->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - videod_interface_t *self = &_videod_itf[ctl_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VC_CTL_VIDEO_POWER_MODE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VC_CTL_REQUEST_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - uint_fast8_t entity_id; - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); - - case TUSB_REQ_TYPE_CLASS: - entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { - return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); - } else { - TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); - return VIDEO_ERROR_NONE; - } - - default: - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); - TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); - uint8_t alt_num = vs->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - (void)rhport; - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VS_CTL_STREAM_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - /* TODO */ - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_PROBE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), - VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_MAX: - case VIDEO_REQUEST_GET_RES: - case VIDEO_REQUEST_GET_DEF: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - video_probe_and_commit_control_t tmp; - tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; - TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t)&_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_COMMIT: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_DATA) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - if (tud_video_commit_cb) { - return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); - } - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_STILL_PROBE: - case VIDEO_VS_CTL_STILL_COMMIT: - case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: - case VIDEO_VS_CTL_GENERATE_KEY_FRAME: - case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: - case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: - /* TODO */ - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_stm_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_stm_std_req(rhport, stage, request, stm_idx); - - case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; - return handle_video_stm_cs_req(rhport, stage, request, stm_idx); - - default: return VIDEO_ERROR_INVALID_REQUEST; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; - return false; -} - -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - return true; -} - -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - - /* Find EP address */ - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - uint8_t ep_addr = 0; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; - ep_addr = _desc_ep_addr(desc + ofs_ep); - break; - } - if (!ep_addr) return false; - - TU_VERIFY( usbd_edpt_claim(0, ep_addr) ); - /* update the packet header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->FrameID ^= 1; - hdr->EndOfFrame = 0; - /* update the packet data */ - stm->buffer = (uint8_t*)buffer; - stm->bufsize = bufsize; - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void videod_init(void) -{ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -void videod_reset(uint8_t rhport) -{ - (void) rhport; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && - (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && - (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); - - /* Find available interface */ - videod_interface_t *self = NULL; - uint8_t ctl_idx; - for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; - self = &_videod_itf[ctl_idx]; - break; - } - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); - - uint8_t const *end = (uint8_t const*)itf_desc + max_len; - self->beg = (uint8_t const*) itf_desc; - self->len = max_len; - - /*------------- Video Control Interface -------------*/ - TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - uint_fast8_t bInCollection = vc->ctl.bInCollection; - - /* Find the end of the video interface descriptor */ - void const *cur = _next_desc_itf(itf_desc, end); - for (uint8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { - videod_streaming_interface_t *stm = NULL; - /* find free streaming interface handle */ - for (uint8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; - stm = &_videod_streaming_itf[i]; - self->stm[stm_idx] = i; - break; - } - TU_ASSERT(stm, 0); - stm->index_vc = ctl_idx; - stm->index_vs = stm_idx; - stm->desc.beg = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - cur = _next_desc_itf(cur, end); - stm->desc.end = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - } - self->len = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); - return (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - int err; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - uint_fast8_t itfnum = tu_u16_low(request->wIndex); - - /* Identify which control interface to use */ - uint_fast8_t itf; - for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { - void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; - } - - if (itf < CFG_TUD_VIDEO) { - err = handle_video_ctl_req(rhport, stage, request, itf); - _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - - /* Identify which streaming interface to use */ - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; - uint8_t const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; - } - - if (itf < CFG_TUD_VIDEO_STREAMING) { - err = handle_video_stm_req(rhport, stage, request, itf); - _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - return false; -} - -bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; (void)xferred_bytes; - - /* find streaming handle */ - uint_fast8_t itf; - videod_interface_t *ctl; - videod_streaming_interface_t *stm; - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - stm = &_videod_streaming_itf[itf]; - uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; - ctl = &_videod_itf[stm->index_vc]; - uint8_t const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; - } - - TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); - if (stm->offset < stm->bufsize) { - /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, (uint16_t) pkt_len), 0); - } else { - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - if (tud_video_frame_xfer_complete_cb) { - tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); - } - } - return true; -} - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.h b/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.h deleted file mode 100644 index ee2fcb9d..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/class/video/video_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_DEVICE_H_ -#define TUSB_VIDEO_DEVICE_H_ - -#include "common/tusb_common.h" -#include "video.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_VIDEO > 1 -//--------------------------------------------------------------------+ - -/** Return true if streaming - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -/** Transfer a frame - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. - * @param[in] bufsize Byte size of the frame buffer */ -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); - -/*------------- Optional callbacks -------------*/ -/** Invoked when compeletion of a frame transfer - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -/** Invoked when SET_POWER_MODE request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); - -/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] parameters Video streaming parameters - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void videod_init (void); -void videod_reset (uint8_t rhport); -uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_common.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_common.h index 957491aa..0d4082c0 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_common.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_common.h @@ -37,6 +37,7 @@ #define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) #define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low))) #define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) @@ -53,6 +54,8 @@ #define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) #define TU_BIT(n) (1UL << (n)) + +// Generate a mask with bit from high (31) to low (0) set, e.g TU_GENMASK(3, 0) = 0b1111 #define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) //--------------------------------------------------------------------+ @@ -62,6 +65,7 @@ // Standard Headers #include #include +#include #include #include #include @@ -73,8 +77,6 @@ #include "tusb_types.h" #include "tusb_debug.h" -#include "tusb_timeout.h" // TODO remove - //--------------------------------------------------------------------+ // Optional API implemented by application if needed // TODO move to a more ovious place/file @@ -99,10 +101,9 @@ TU_ATTR_WEAK extern void* tusb_app_phys_to_virt(void *phys_addr); #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) // This is a backport of memset_s from c11 -TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) -{ +TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) { // TODO may check if desst and src is not NULL - if (count > destsz) { + if ( count > destsz ) { return -1; } memset(dest, ch, count); @@ -110,10 +111,9 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, i } // This is a backport of memcpy_s from c11 -TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void * src, size_t count ) -{ +TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) { // TODO may check if desst and src is not NULL - if (count > destsz) { + if ( count > destsz ) { return -1; } memcpy(dest, src, count); @@ -122,13 +122,11 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) { return (uint16_t) ((((uint16_t) high) << 8) | low); } @@ -159,16 +157,20 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } //------------- Align -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) { return value & ((uint32_t) ~(alignment-1)); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4 (uint32_t value) { return (value & 0xFFFFFFFCUL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align8 (uint32_t value) { return (value & 0xFFFFFFF8UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned32(uint32_t value) { return (value & 0x1FUL) == 0; } +TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { return (value & 0x3FUL) == 0; } + //------------- Mathematics -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } @@ -260,11 +262,21 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_ #else // MCU that could access unaligned memory natively -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void *mem) { + return *((uint32_t const *) mem); +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) { + return *((uint16_t const *) mem); +} -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void *mem, uint32_t value) { + *((uint32_t *) mem) = value; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_t value) { + *((uint16_t *) mem) = value; +} #endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_compiler.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_compiler.h index 5ab56e14..0d5570b1 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_compiler.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_compiler.h @@ -56,7 +56,7 @@ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert #elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, _TU_COUNTER_)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif @@ -128,7 +128,9 @@ #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #endif #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used @@ -205,7 +207,9 @@ #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #endif #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_debug.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_debug.h index 82f68204..2e9f1d9c 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_debug.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_debug.h @@ -43,9 +43,10 @@ #if CFG_TUSB_DEBUG // Enum to String for debugging purposes -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL extern char const* const tu_str_speed[]; extern char const* const tu_str_std_request[]; +extern char const* const tu_str_xfer_result[]; #endif void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); @@ -57,16 +58,15 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #define tu_printf printf #endif -static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) -{ +static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_ARR TU_LOG1_ARR - #define TU_LOG2_PTR TU_LOG1_PTR + #define TU_LOG2_BUF TU_LOG1_BUF #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX #endif @@ -94,30 +92,25 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #if CFG_TUSB_DEBUG >= 3 #define TU_LOG3 TU_LOG1 #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_ARR TU_LOG1_ARR - #define TU_LOG3_PTR TU_LOG1_PTR + #define TU_LOG3_BUF TU_LOG1_BUF #define TU_LOG3_INT TU_LOG1_INT #define TU_LOG3_HEX TU_LOG1_HEX #endif -typedef struct -{ +typedef struct { uint32_t key; const char* data; } tu_lookup_entry_t; -typedef struct -{ +typedef struct { uint16_t count; tu_lookup_entry_t const* items; } tu_lookup_table_t; -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { tu_static char not_found[11]; - for(uint16_t i=0; icount; i++) - { + for(uint16_t i=0; icount; i++) { if (p_table->items[i].key == key) return p_table->items[i].data; } @@ -132,7 +125,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG #define TU_LOG(n, ...) #define TU_LOG_MEM(n, ...) - #define TU_LOG_PTR(n, ...) + #define TU_LOG_BUF(n, ...) #define TU_LOG_INT(n, ...) #define TU_LOG_HEX(n, ...) #define TU_LOG_LOCATION() @@ -143,14 +136,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG0(...) #define TU_LOG0_MEM(...) -#define TU_LOG0_PTR(...) +#define TU_LOG0_BUF(...) #define TU_LOG0_INT(...) #define TU_LOG0_HEX(...) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) - #define TU_LOG1_PTR(...) + #define TU_LOG1_BUF(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) #endif @@ -158,7 +151,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) - #define TU_LOG2_PTR(...) + #define TU_LOG2_BUF(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) #endif @@ -166,7 +159,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG3 #define TU_LOG3(...) #define TU_LOG3_MEM(...) - #define TU_LOG3_PTR(...) + #define TU_LOG3_BUF(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) #endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.c b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.c index a52c9226..76696396 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.c +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.c @@ -224,6 +224,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); } break; + default: break; } } @@ -539,7 +540,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance index f->wr_idx = advance_index(f->depth, wr_idx, n); - TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\n", f->wr_idx); + TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); } _ff_unlock(f->mutex_wr); diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.h index 2f60ec2f..2d9f5e66 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_fifo.h @@ -102,10 +102,8 @@ extern "C" { * | * ------------------------- * | R | 1 | 2 | W | 4 | 5 | - */ -typedef struct -{ +typedef struct { uint8_t* buffer ; // buffer pointer uint16_t depth ; // max items @@ -124,16 +122,14 @@ typedef struct } tu_fifo_t; -typedef struct -{ +typedef struct { uint16_t len_lin ; ///< linear length in item size uint16_t len_wrap ; ///< wrapped length in item size void * ptr_lin ; ///< linear part start pointer void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ -{ \ +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\ .buffer = _buffer, \ .depth = _depth, \ .item_size = sizeof(_type), \ @@ -144,23 +140,18 @@ typedef struct uint8_t _name##_buf[_depth*sizeof(_type)]; \ tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) - bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if OSAL_MUTEX_REQUIRED -TU_ATTR_ALWAYS_INLINE static inline -void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) -{ - f->mutex_wr = wr_mutex; - f->mutex_rd = rd_mutex; -} - + TU_ATTR_ALWAYS_INLINE static inline + void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) { + f->mutex_wr = wr_mutex; + f->mutex_rd = rd_mutex; + } #else - -#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) - + #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif bool tu_fifo_write (tu_fifo_t* f, void const * p_data); @@ -182,8 +173,7 @@ bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) -{ +uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; } @@ -198,7 +188,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - #ifdef __cplusplus } #endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_mcu.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_mcu.h index ba8976a8..5a567f2d 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_mcu.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_mcu.h @@ -34,10 +34,16 @@ //------------- Unaligned Memory Access -------------// -// ARMv7+ (M3-M7, M23-M33) can access unaligned memory -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) - #define TUP_ARCH_STRICT_ALIGN 0 +#ifdef __ARM_ARCH + // ARM Architecture set __ARM_FEATURE_UNALIGNED to 1 for mcu supports unaligned access + #if defined(__ARM_FEATURE_UNALIGNED) && __ARM_FEATURE_UNALIGNED == 1 + #define TUP_ARCH_STRICT_ALIGN 0 + #else + #define TUP_ARCH_STRICT_ALIGN 1 + #endif #else + // TODO default to strict align for others + // Should investigate other architecture such as risv, xtensa, mips for optimal setting #define TUP_ARCH_STRICT_ALIGN 1 #endif @@ -52,6 +58,7 @@ // NXP //--------------------------------------------------------------------+ #if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) @@ -59,33 +66,55 @@ #define TUP_USBIP_OHCI #define TUP_OHCI_RHPORTS 2 -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - // TODO USB0 has 6, USB1 has 4 - #define TUP_USBIP_CHIPIDEA_HS - #define TUP_USBIP_EHCI - - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 FS - #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC54) // TODO USB0 has 5, USB1 has 6 + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 + #define TUP_USBIP_IP3511 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT) +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + // USB0 has 6 with HS PHY, USB1 has 4 only FS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_MCXN9) + // USB0 is chipidea FS + #define TUP_USBIP_CHIPIDEA_FS + #define TUP_USBIP_CHIPIDEA_FS_MCX + + // USB1 is chipidea HS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_MCXA15) + // USB0 is chipidea FS + #define TUP_USBIP_CHIPIDEA_FS + #define TUP_USBIP_CHIPIDEA_FS_MCX + + #define TUP_DCD_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 HS + #define TUP_RHPORT_HIGHSPEED 1 -#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32) +#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K) #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_KINETIS #define TUP_DCD_ENDPOINT_MAX 16 @@ -188,7 +217,22 @@ #define TUP_DCD_ENDPOINT_MAX 9 +#elif TU_CHECK_MCU(OPT_MCU_STM32H5) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_STM32G4) + // Device controller + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + + // TypeC controller + #define TUP_USBIP_TYPEC_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_TYPEC_RHPORTS_NUM 1 + +#elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 @@ -227,14 +271,21 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32U5) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 6 + + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY + #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ + defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 + #else + #define TUP_DCD_ENDPOINT_MAX 6 + #endif #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 - //--------------------------------------------------------------------+ // Sony //--------------------------------------------------------------------+ @@ -278,6 +329,9 @@ #define TUP_USBIP_DWC2 #define TUP_DCD_ENDPOINT_MAX 6 +#elif TU_CHECK_MCU(OPT_MCU_ESP32) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) + #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + //--------------------------------------------------------------------+ // Dialog //--------------------------------------------------------------------+ @@ -303,6 +357,7 @@ // Renesas //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N, OPT_MCU_RAXXX) + #define TUP_USBIP_RUSB2 #define TUP_DCD_ENDPOINT_MAX 10 //--------------------------------------------------------------------+ @@ -348,8 +403,24 @@ #elif TU_CHECK_MCU(OPT_MCU_CH32V307) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_CH32F20X) + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 +#endif + + +//--------------------------------------------------------------------+ +// External USB controller +//--------------------------------------------------------------------+ + +#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #endif #endif + //--------------------------------------------------------------------+ // Default Values //--------------------------------------------------------------------+ @@ -358,8 +429,8 @@ #define TUP_MCU_MULTIPLE_CORE 0 #endif -#ifndef TUP_DCD_ENDPOINT_MAX - #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" +#if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED +#warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 #endif @@ -373,4 +444,8 @@ #define TU_ATTR_FAST_FUNC #endif +#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) + #define TUP_DCD_EDPT_ISO_ALLOC +#endif + #endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_private.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_private.h index d5541856..373a5025 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_private.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_private.h @@ -60,7 +60,7 @@ typedef struct { tu_fifo_t ff; // mutex: read if ep rx, write if e tx - OSAL_MUTEX_DEF(ff_mutex); + OSAL_MUTEX_DEF(ff_mutexdef); }tu_edpt_stream_t; @@ -87,15 +87,17 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); // Endpoint Stream //--------------------------------------------------------------------+ -// Init an stream, should only be called once +// Init an endpoint stream bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize); +// Deinit an endpoint stream +bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); + // Open an stream for an endpoint // hwid is either device address (host mode) or rhport (device mode) TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) -{ +void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) { tu_fifo_clear(&s->ff); s->hwid = hwid; s->ep_addr = desc_ep->bEndpointAddress; @@ -103,16 +105,14 @@ void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t } TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_close(tu_edpt_stream_t* s) -{ +void tu_edpt_stream_close(tu_edpt_stream_t* s) { s->hwid = 0; s->ep_addr = 0; } // Clear fifo TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_clear(tu_edpt_stream_t* s) -{ +bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { return tu_fifo_clear(&s->ff); } @@ -131,8 +131,7 @@ bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferr // Get the number of bytes available for writing TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) { return (uint32_t) tu_fifo_remaining(&s->ff); } @@ -148,21 +147,26 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s); // Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) -{ +void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } +// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes +TU_ATTR_ALWAYS_INLINE static inline +void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) { + if (skip_offset < xferred_bytes) { + tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset)); + } +} + // Get the number of bytes available for reading TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) { return (uint32_t) tu_fifo_count(&s->ff); } TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) -{ +bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) { return tu_fifo_peek(&s->ff, ch); } diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_timeout.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_timeout.h deleted file mode 100644 index 533e67ab..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_timeout.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - -#ifndef _TUSB_TIMEOUT_H_ -#define _TUSB_TIMEOUT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}tu_timeout_t; - -#if 0 - -extern uint32_t tusb_hal_millis(void); - -static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool tu_timeout_expired(tu_timeout_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -// For used with periodic event to prevent drift -static inline void tu_timeout_reset(tu_timeout_t* tt) -{ - tt->start += tt->interval; -} - -static inline void tu_timeout_restart(tu_timeout_t* tt) -{ - tt->start = tusb_hal_millis(); -} - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_H_ */ - -/** @} */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_types.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_types.h index 39a2d456..b571f9b7 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_types.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_types.h @@ -24,12 +24,8 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usb_definitions - * \defgroup USBDef_Type USB Types - * @{ */ - -#ifndef _TUSB_TYPES_H_ -#define _TUSB_TYPES_H_ +#ifndef TUSB_TYPES_H_ +#define TUSB_TYPES_H_ #include #include @@ -44,43 +40,38 @@ *------------------------------------------------------------------*/ /// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ +typedef enum { TUSB_SPEED_FULL = 0, TUSB_SPEED_LOW = 1, TUSB_SPEED_HIGH = 2, TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; +} tusb_speed_t; /// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ +typedef enum { TUSB_XFER_CONTROL = 0 , TUSB_XFER_ISOCHRONOUS , TUSB_XFER_BULK , TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; +} tusb_xfer_type_t; -typedef enum -{ +typedef enum { TUSB_DIR_OUT = 0, TUSB_DIR_IN = 1, TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; +} tusb_dir_t; -enum -{ +enum { TUSB_EPSIZE_BULK_FS = 64, - TUSB_EPSIZE_BULK_HS= 512, + TUSB_EPSIZE_BULK_HS = 512, TUSB_EPSIZE_ISO_FS_MAX = 1023, TUSB_EPSIZE_ISO_HS_MAX = 1024, }; -/// Isochronous End Point Attributes -typedef enum -{ +/// Isochronous Endpoint Attributes +typedef enum { TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, @@ -88,11 +79,10 @@ typedef enum TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; +} tusb_iso_ep_attribute_t; /// USB Descriptor Types -typedef enum -{ +typedef enum { TUSB_DESC_DEVICE = 0x01, TUSB_DESC_CONFIGURATION = 0x02, TUSB_DESC_STRING = 0x03, @@ -119,10 +109,9 @@ typedef enum TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; +} tusb_desc_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_GET_STATUS = 0 , TUSB_REQ_CLEAR_FEATURE = 1 , TUSB_REQ_RESERVED = 2 , @@ -136,25 +125,22 @@ typedef enum TUSB_REQ_GET_INTERFACE = 10 , TUSB_REQ_SET_INTERFACE = 11 , TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; +} tusb_request_code_t; -typedef enum -{ +typedef enum { TUSB_REQ_FEATURE_EDPT_HALT = 0, TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; +} tusb_request_feature_selector_t; -typedef enum -{ +typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID } tusb_request_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_RCPT_DEVICE =0, TUSB_REQ_RCPT_INTERFACE, TUSB_REQ_RCPT_ENDPOINT, @@ -162,8 +148,7 @@ typedef enum } tusb_request_recipient_t; // https://www.usb.org/defined-class-codes -typedef enum -{ +typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , TUSB_CLASS_AUDIO = 1 , TUSB_CLASS_CDC = 2 , @@ -187,26 +172,23 @@ typedef enum TUSB_CLASS_MISC = 0xEF , TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; +} tusb_class_code_t; typedef enum { MISC_SUBCLASS_COMMON = 2 }misc_subclass_type_t; -typedef enum -{ +typedef enum { MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; +} misc_protocol_type_t; -typedef enum -{ +typedef enum { APP_SUBCLASS_USBTMC = 0x03, APP_SUBCLASS_DFU_RUNTIME = 0x01 } app_subclass_type_t; -typedef enum -{ +typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, @@ -223,37 +205,37 @@ typedef enum DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; +} device_capability_type_t; enum { - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), - TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = 1u << 5, + TUSB_DESC_CONFIG_ATT_SELF_POWERED = 1u << 6, }; #define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) -typedef enum -{ +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +typedef enum { XFER_RESULT_SUCCESS = 0, XFER_RESULT_FAILED, XFER_RESULT_STALLED, XFER_RESULT_TIMEOUT, XFER_RESULT_INVALID -}xfer_result_t; +} xfer_result_t; -enum // TODO remove -{ +// TODO remove +enum { DESC_OFFSET_LEN = 0, DESC_OFFSET_TYPE = 1 }; -enum -{ +enum { INTERFACE_INVALID_NUMBER = 0xff }; -typedef enum -{ +typedef enum { MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, @@ -265,16 +247,14 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; -enum -{ +enum { CONTROL_STAGE_IDLE, CONTROL_STAGE_SETUP, CONTROL_STAGE_DATA, CONTROL_STAGE_ACK }; -enum -{ +enum { TUSB_INDEX_INVALID_8 = 0xFFu }; @@ -287,15 +267,14 @@ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. - uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. + uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). - uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. - uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. + uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). + uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). @@ -311,8 +290,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this descriptor @@ -322,8 +300,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); /// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. @@ -338,8 +315,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); /// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type @@ -355,8 +331,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); /// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; // Size of this descriptor in bytes uint8_t bDescriptorType ; // ENDPOINT Descriptor Type @@ -376,8 +351,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); /// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type uint16_t wTotalLength ; ///< Total length of data returned @@ -390,8 +364,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_other_speed_t; /// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Device Qualifier Type uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) @@ -408,8 +381,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); /// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type @@ -423,17 +395,17 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct"); + // USB String Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; // USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType ; uint8_t bDevCapabilityType; @@ -442,9 +414,8 @@ typedef struct TU_ATTR_PACKED uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ +// USB WebUSB URL Descriptor +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bScheme; @@ -452,8 +423,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -474,10 +444,11 @@ typedef struct TU_ATTR_PACKED uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -/*------------------------------------------------------------------*/ -/* Types - *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. @@ -496,7 +467,6 @@ typedef struct TU_ATTR_PACKED{ TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END @@ -505,36 +475,25 @@ TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Get direction from Endpoint address -TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; } // Get Endpoint number from address -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ - return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { + return tu_le16toh(desc_ep->wMaxPacketSize) & 0x7FF; } #if CFG_TUSB_DEBUG -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) -{ - tu_static const char *str[] = {"out", "in"}; - return str[dir]; -} - -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) { tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"}; return str[t]; } @@ -545,21 +504,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_ //--------------------------------------------------------------------+ // return next descriptor -TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { uint8_t const* desc8 = (uint8_t const*) desc; return desc8 + desc8[DESC_OFFSET_LEN]; } // get descriptor type -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } // get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; } @@ -576,6 +532,4 @@ uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t b } #endif -#endif /* _TUSB_TYPES_H_ */ - -/** @} */ +#endif // TUSB_TYPES_H_ diff --git a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_verify.h b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_verify.h index 12355e8b..0a9549c9 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/common/tusb_verify.h +++ b/test-devices/loopback-stm32/lib/tinyusb/common/tusb_verify.h @@ -56,12 +56,8 @@ * #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond,ret) if(cond) return ret; * - * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} - * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} - * * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -79,15 +75,16 @@ #define _MESS_FAILED() do {} while (0) #endif -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \ + defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do \ { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#elif defined(__riscv) +#elif defined(__riscv) && !TUP_MCU_ESPRESSIF #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) #elif defined(_mips) @@ -97,40 +94,23 @@ #define TU_BREAKPOINT() do {} while (0) #endif -/*------------------------------------------------------------------*/ -/* Macro Generator - *------------------------------------------------------------------*/ - // Helper to implement optional parameter for TU_VERIFY Macro family #define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 - -/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ -#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ -{ \ - if ( !(_cond) ) { _handler; return _ret; } \ -} while(0) /*------------------------------------------------------------------*/ /* TU_VERIFY * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) -#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { return _ret; } \ + } while(0) -#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) - -/*------------------------------------------------------------------*/ -/* TU_VERIFY WITH HANDLER - * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) -#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) - -#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) +#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT @@ -138,19 +118,20 @@ * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) +#define TU_ASSERT_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \ + } while(0) + +#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false) +#define TU_ASSERT_2ARGS(_cond, _ret) TU_ASSERT_DEFINE(_cond, _ret) #ifndef TU_ASSERT -#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__) #endif -/*------------------------------------------------------------------*/ -/* ASSERT HDLR - *------------------------------------------------------------------*/ - #ifdef __cplusplus } #endif -#endif /* TUSB_VERIFY_H_ */ +#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/device/dcd.h b/test-devices/loopback-stm32/lib/tinyusb/device/dcd.h index 00419ff0..d4f105aa 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/device/dcd.h +++ b/test-devices/loopback-stm32/lib/tinyusb/device/dcd.h @@ -47,8 +47,7 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -typedef enum -{ +typedef enum { DCD_EVENT_INVALID = 0, DCD_EVENT_BUS_RESET, DCD_EVENT_UNPLUGGED, @@ -65,13 +64,11 @@ typedef enum DCD_EVENT_COUNT } dcd_eventid_t; -typedef struct TU_ATTR_ALIGNED(4) -{ +typedef struct TU_ATTR_ALIGNED(4) { uint8_t rhport; uint8_t event_id; - union - { + union { // BUS RESET struct { tusb_speed_t speed; @@ -102,12 +99,31 @@ typedef struct TU_ATTR_ALIGNED(4) //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); +//--------------------------------------------------------------------+ +// Memory API +//--------------------------------------------------------------------+ + +// clean/flush data cache: write cache -> memory. +// Required before an DMA TX transfer to make sure data is in memory +void dcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + +// invalidate data cache: mark cache as invalid, next read will read from memory +// Required BOTH before and after an DMA RX transfer +void dcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + +// clean and invalidate data cache +// Required before an DMA transfer where memory is both read/write by DMA +void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ // Initialize controller to device mode -void dcd_init (uint8_t rhport); +void dcd_init(uint8_t rhport); + +// Deinitialize controller, unset device mode. +bool dcd_deinit(uint8_t rhport); // Interrupt Handler void dcd_int_handler(uint8_t rhport); @@ -139,7 +155,7 @@ void dcd_sof_enable(uint8_t rhport, bool en); // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request); // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); @@ -168,11 +184,12 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); // Allocate packet buffer used by ISO endpoints -// Some MCU need manual packet buffer allocation, we allocation largest size to avoid clustering +// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); // Configure and enable an ISO endpoint according to descriptor -TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ @@ -181,23 +198,20 @@ TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t co extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); // helper to send bus signal event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = eid }; dcd_event_handler(&event, in_isr); } // helper to send bus reset event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; event.bus_reset.speed = speed; dcd_event_handler(&event, in_isr); } // helper to send setup received -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); @@ -205,8 +219,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport } // helper to send transfer complete event -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; event.xfer_complete.ep_addr = ep_addr; @@ -216,8 +229,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport dcd_event_handler(&event, in_isr); } -static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SOF }; event.sof.frame_count = frame_count; dcd_event_handler(&event, in_isr); diff --git a/test-devices/loopback-stm32/lib/tinyusb/device/usbd.c b/test-devices/loopback-stm32/lib/tinyusb/device/usbd.c index cee56af6..e51aa0fc 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/device/usbd.c +++ b/test-devices/loopback-stm32/lib/tinyusb/device/usbd.c @@ -38,13 +38,23 @@ //--------------------------------------------------------------------+ // USBD Configuration //--------------------------------------------------------------------+ - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -// Debug level of USBD -#define USBD_DBG 2 +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) { + (void) rhport; + return false; +} + +TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { + (void)rhport; + (void)eventid; + (void)in_isr; +} //--------------------------------------------------------------------+ // Device Data @@ -53,10 +63,8 @@ // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; -typedef struct -{ - struct TU_ATTR_PACKED - { +typedef struct { + struct TU_ATTR_PACKED { volatile uint8_t connected : 1; volatile uint8_t addressed : 1; volatile uint8_t suspended : 1; @@ -65,9 +73,9 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; - volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; + volatile uint8_t setup_count; uint8_t itf2drv[CFG_TUD_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each @@ -81,158 +89,169 @@ tu_static usbd_device_t _usbd_dev; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL #define DRIVER_NAME(_name) .name = _name, #else #define DRIVER_NAME(_name) #endif // Built-in class drivers -tu_static usbd_class_driver_t const _usbd_driver[] = -{ - #if CFG_TUD_CDC - { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MSC - { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_HID - { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_AUDIO - { - DRIVER_NAME("AUDIO") - .init = audiod_init, - .reset = audiod_reset, - .open = audiod_open, - .control_xfer_cb = audiod_control_xfer_cb, - .xfer_cb = audiod_xfer_cb, - .sof = audiod_sof_isr - }, - #endif - - #if CFG_TUD_VIDEO - { - DRIVER_NAME("VIDEO") - .init = videod_init, - .reset = videod_reset, - .open = videod_open, - .control_xfer_cb = videod_control_xfer_cb, - .xfer_cb = videod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MIDI - { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VENDOR - { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_xfer_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_USBTMC - { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_xfer_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU_RUNTIME - { - DRIVER_NAME("DFU-RUNTIME") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU - { - DRIVER_NAME("DFU") - .init = dfu_moded_init, - .reset = dfu_moded_reset, - .open = dfu_moded_open, - .control_xfer_cb = dfu_moded_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM - { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_xfer_cb, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - #endif - - #if CFG_TUD_BTH - { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_xfer_cb, - .xfer_cb = btd_xfer_cb, - .sof = NULL - }, - #endif +tu_static usbd_class_driver_t const _usbd_driver[] = { + #if CFG_TUD_CDC + { + DRIVER_NAME("CDC") + .init = cdcd_init, + .deinit = cdcd_deinit, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MSC + { + DRIVER_NAME("MSC") + .init = mscd_init, + .deinit = NULL, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_HID + { + DRIVER_NAME("HID") + .init = hidd_init, + .deinit = hidd_deinit, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") + .init = audiod_init, + .deinit = audiod_deinit, + .reset = audiod_reset, + .open = audiod_open, + .control_xfer_cb = audiod_control_xfer_cb, + .xfer_cb = audiod_xfer_cb, + .sof = audiod_sof_isr + }, + #endif + + #if CFG_TUD_VIDEO + { + DRIVER_NAME("VIDEO") + .init = videod_init, + .deinit = videod_deinit, + .reset = videod_reset, + .open = videod_open, + .control_xfer_cb = videod_control_xfer_cb, + .xfer_cb = videod_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MIDI + { + DRIVER_NAME("MIDI") + .init = midid_init, + .deinit = midid_deinit, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_VENDOR + { + DRIVER_NAME("VENDOR") + .init = vendord_init, + .deinit = vendord_deinit, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_xfer_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_USBTMC + { + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .deinit = usbtmcd_deinit, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU_RUNTIME + { + DRIVER_NAME("DFU-RUNTIME") + .init = dfu_rtd_init, + .deinit = dfu_rtd_deinit, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU + { + DRIVER_NAME("DFU") + .init = dfu_moded_init, + .deinit = dfu_moded_deinit, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM + { + DRIVER_NAME("NET") + .init = netd_init, + .deinit = netd_deinit, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_xfer_cb, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, + #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .deinit = btd_deinit, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_xfer_cb, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; @@ -241,25 +260,21 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; tu_static usbd_class_driver_t const * _app_driver = NULL; tu_static uint8_t _app_driver_count = 0; +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) + // virtually joins built-in and application drivers together. // Application is positioned first to allow overwriting built-in ones. -static inline usbd_class_driver_t const * get_driver(uint8_t drvid) -{ - // Application drivers - if ( usbd_app_driver_get_cb ) - { - if ( drvid < _app_driver_count ) return &_app_driver[drvid]; - drvid -= _app_driver_count; +TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { + usbd_class_driver_t const * driver = NULL; + if ( drvid < _app_driver_count ) { + // Application drivers + driver = &_app_driver[drvid]; + } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){ + driver = &_usbd_driver[drvid - _app_driver_count]; } - - // Built-in drivers - if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; - - return NULL; + return driver; } -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) - //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ @@ -280,6 +295,11 @@ tu_static osal_queue_t _usbd_q; #define _usbd_mutex NULL #endif +TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) { + TU_ASSERT(osal_queue_send(_usbd_q, event, in_isr)); + tud_event_hook_cb(event->rhport, event->event_id, in_isr); + return true; +} //--------------------------------------------------------------------+ // Prototypes @@ -298,29 +318,25 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 -tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = -{ - "Invalid" , - "Bus Reset" , - "Unplugged" , - "SOF" , - "Suspend" , - "Resume" , - "Setup Received" , - "Xfer Complete" , - "Func Call" +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL +tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { + "Invalid", + "Bus Reset", + "Unplugged", + "SOF", + "Suspend", + "Resume", + "Setup Received", + "Xfer Complete", + "Func Call" }; // for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) -{ - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver && driver->control_xfer_cb == callback ) - { - TU_LOG(USBD_DBG, " %s control complete\r\n", driver->name); +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if (driver && driver->control_xfer_cb == callback) { + TU_LOG_USBD("%s control complete\r\n", driver->name); return; } } @@ -331,43 +347,36 @@ void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -tusb_speed_t tud_speed_get(void) -{ +tusb_speed_t tud_speed_get(void) { return (tusb_speed_t) _usbd_dev.speed; } -bool tud_connected(void) -{ +bool tud_connected(void) { return _usbd_dev.connected; } -bool tud_mounted(void) -{ +bool tud_mounted(void) { return _usbd_dev.cfg_num ? true : false; } -bool tud_suspended(void) -{ +bool tud_suspended(void) { return _usbd_dev.suspended; } -bool tud_remote_wakeup(void) -{ +bool tud_remote_wakeup(void) { // only wake up host if this feature is supported and enabled and we are suspended - TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); + TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en); dcd_remote_wakeup(_usbd_rhport); return true; } -bool tud_disconnect(void) -{ +bool tud_disconnect(void) { TU_VERIFY(dcd_disconnect); dcd_disconnect(_usbd_rhport); return true; } -bool tud_connect(void) -{ +bool tud_connect(void) { TU_VERIFY(dcd_connect); dcd_connect(_usbd_rhport); return true; @@ -376,20 +385,19 @@ bool tud_connect(void) //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ -bool tud_inited(void) -{ +bool tud_inited(void) { return _usbd_rhport != RHPORT_INVALID; } -bool tud_init (uint8_t rhport) -{ +bool tud_init(uint8_t rhport) { // skip if already initialized - if ( tud_inited() ) return true; + if (tud_inited()) return true; - TU_LOG(USBD_DBG, "USBD init on controller %u\r\n", rhport); - TU_LOG_INT(USBD_DBG, sizeof(usbd_device_t)); - TU_LOG_INT(USBD_DBG, sizeof(tu_fifo_t)); - TU_LOG_INT(USBD_DBG, sizeof(tu_edpt_stream_t)); + TU_LOG_USBD("USBD init on controller %u\r\n", rhport); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t)); + TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t)); tu_varclr(&_usbd_dev); @@ -404,17 +412,15 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( usbd_app_driver_get_cb ) - { + if (usbd_app_driver_get_cb) { _app_driver = usbd_app_driver_get_cb(&_app_driver_count); } // Init class drivers - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_ASSERT(driver); - TU_LOG(USBD_DBG, "%s init\r\n", driver->name); + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + TU_ASSERT(driver && driver->init); + TU_LOG_USBD("%s init\r\n", driver->name); driver->init(); } @@ -427,31 +433,61 @@ bool tud_init (uint8_t rhport) return true; } -static void configuration_reset(uint8_t rhport) -{ - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_ASSERT(driver, ); +bool tud_deinit(uint8_t rhport) { + // skip if not initialized + if (!tud_inited()) return true; + + TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport); + + // Deinit device controller driver + dcd_int_disable(rhport); + dcd_disconnect(rhport); + dcd_deinit(rhport); + + // Deinit class drivers + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if(driver && driver->deinit) { + TU_LOG_USBD("%s deinit\r\n", driver->name); + driver->deinit(); + } + } + + // Deinit device queue & task + osal_queue_delete(_usbd_q); + _usbd_q = NULL; + +#if OSAL_MUTEX_REQUIRED + // TODO make sure there is no task waiting on this mutex + osal_mutex_delete(_usbd_mutex); + _usbd_mutex = NULL; +#endif + + _usbd_rhport = RHPORT_INVALID; + + return true; +} + +static void configuration_reset(uint8_t rhport) { + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + TU_ASSERT(driver,); driver->reset(rhport); } tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping + memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } -static void usbd_reset(uint8_t rhport) -{ +static void usbd_reset(uint8_t rhport) { configuration_reset(rhport); usbd_control_reset(); } -bool tud_task_event_ready(void) -{ +bool tud_task_event_ready(void) { // Skip if stack is not initialized - if ( !tud_inited() ) return false; - + if (!tud_inited()) return false; return !osal_queue_empty(_usbd_q); } @@ -459,139 +495,126 @@ bool tud_task_event_ready(void) * This top level thread manages all device controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. * - @code - int main(void) - { + int main(void) { application_init(); tusb_init(); - while(1) // the mainloop - { + while(1) { // the mainloop application_code(); tud_task(); // tinyusb device task } } - @endcode */ -void tud_task_ext(uint32_t timeout_ms, bool in_isr) -{ +void tud_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized - if ( !tud_inited() ) return; + if (!tud_inited()) return; // Loop until there is no more events in the queue - while (1) - { + while (1) { dcd_event_t event; - if ( !osal_queue_receive(_usbd_q, &event, timeout_ms) ) return; + if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return; -#if CFG_TUSB_DEBUG >= 2 - if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG(USBD_DBG, "\r\n"); // extra line for setup - TU_LOG(USBD_DBG, "USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup + TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); #endif - switch ( event.event_id ) - { + switch (event.event_id) { case DCD_EVENT_BUS_RESET: - TU_LOG(USBD_DBG, ": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); + TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; - break; + break; case DCD_EVENT_UNPLUGGED: - TU_LOG(USBD_DBG, "\r\n"); + TU_LOG_USBD("\r\n"); usbd_reset(event.rhport); - - // invoke callback if (tud_umount_cb) tud_umount_cb(); - break; + break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG_PTR(USBD_DBG, &event.setup_received); - TU_LOG(USBD_DBG, "\r\n"); + _usbd_dev.setup_count--; + TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); + if (_usbd_dev.setup_count) { + TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n"); + break; + } // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set _usbd_dev.connected = 1; // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0; _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0; // Process control request - if ( !process_control_request(event.rhport, &event.setup_received) ) - { - TU_LOG(USBD_DBG, " Stall EP0\r\n"); + if (!process_control_request(event.rhport, &event.setup_received)) { + TU_LOG_USBD(" Stall EP0\r\n"); // Failed -> stall both control endpoint IN and OUT dcd_edpt_stall(event.rhport, 0); dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); } - break; + break; - case DCD_EVENT_XFER_COMPLETE: - { + case DCD_EVENT_XFER_COMPLETE: { // Invoke the class callback associated with the endpoint address uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG(USBD_DBG, "on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].busy = 0; _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; - if ( 0 == epnum ) - { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); - TU_ASSERT(driver, ); + if (0 == epnum) { + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, + event.xfer_complete.len); + } else { + usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); + TU_ASSERT(driver,); - TU_LOG(USBD_DBG, " %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + TU_LOG_USBD(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } + break; } - break; case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected - if ( _usbd_dev.connected ) - { - TU_LOG(USBD_DBG, ": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); + if (_usbd_dev.connected) { + TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); - }else - { - TU_LOG(USBD_DBG, " Skipped\r\n"); + } else { + TU_LOG_USBD(" Skipped\r\n"); } - break; + break; case DCD_EVENT_RESUME: - if ( _usbd_dev.connected ) - { - TU_LOG(USBD_DBG, "\r\n"); + if (_usbd_dev.connected) { + TU_LOG_USBD("\r\n"); if (tud_resume_cb) tud_resume_cb(); - }else - { - TU_LOG(USBD_DBG, " Skipped\r\n"); + } else { + TU_LOG_USBD(" Skipped\r\n"); } - break; + break; case USBD_EVENT_FUNC_CALL: - TU_LOG(USBD_DBG, "\r\n"); - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; + TU_LOG_USBD("\r\n"); + if (event.func_call.func) event.func_call.func(event.func_call.param); + break; case DCD_EVENT_SOF: default: TU_BREAKPOINT(); - break; + break; } #if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO @@ -606,44 +629,37 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) //--------------------------------------------------------------------+ // Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) -{ +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { usbd_control_set_complete_callback(driver->control_xfer_cb); - TU_LOG(USBD_DBG, " %s control request\r\n", driver->name); + TU_LOG_USBD(" %s control request\r\n", driver->name); return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); } // This handles the actual request and its response. -// return false will cause its caller to stall control endpoint -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ +// Returns false if unable to complete the request, causing caller to stall control endpoints. +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { usbd_control_set_complete_callback(NULL); - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request - if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) - { + if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { TU_VERIFY(tud_vendor_control_xfer_cb); usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } -#if CFG_TUSB_DEBUG >= 2 - if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) - { - TU_LOG(USBD_DBG, " %s", tu_str_std_request[p_request->bRequest]); - if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG(USBD_DBG, "\r\n"); +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) { + TU_LOG_USBD(" %s", tu_str_std_request[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG_USBD("\r\n"); } #endif - switch ( p_request->bmRequestType_bit.recipient ) - { + switch ( p_request->bmRequestType_bit.recipient ) { //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: - if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) { uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); @@ -654,15 +670,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return invoke_class_control(rhport, driver, p_request); } - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported TU_BREAKPOINT(); return false; } - switch ( p_request->bRequest ) - { + switch ( p_request->bRequest ) { case TUSB_REQ_SET_ADDRESS: // Depending on mcu, status phase could be sent either before or after changing device address, // or even require stack to not response with status at all @@ -673,24 +687,20 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.addressed = 1; break; - case TUSB_REQ_GET_CONFIGURATION: - { + case TUSB_REQ_GET_CONFIGURATION: { uint8_t cfg_num = _usbd_dev.cfg_num; tud_control_xfer(rhport, p_request, &cfg_num, 1); } break; - case TUSB_REQ_SET_CONFIGURATION: - { + case TUSB_REQ_SET_CONFIGURATION: { uint8_t const cfg_num = (uint8_t) p_request->wValue; // Only process if new configure is different - if (_usbd_dev.cfg_num != cfg_num) - { - if ( _usbd_dev.cfg_num ) - { + if (_usbd_dev.cfg_num != cfg_num) { + if ( _usbd_dev.cfg_num ) { // already configured: need to clear all endpoints and driver first - TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); + TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); // close all non-control endpoints, cancel all pending transfers if any dcd_edpt_close_all(rhport); @@ -702,8 +712,14 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.speed = speed; // restore speed } - // switch to new configuration if not zero - if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + // Handle the new configuration and execute the corresponding callback + if ( cfg_num ) { + // switch to new configuration if not zero + TU_ASSERT( process_set_config(rhport, cfg_num) ); + if ( tud_mount_cb ) tud_mount_cb(); + } else { + if ( tud_umount_cb ) tud_umount_cb(); + } } _usbd_dev.cfg_num = cfg_num; @@ -719,7 +735,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); + TU_LOG_USBD(" Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; @@ -730,22 +746,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); + TU_LOG_USBD(" Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); break; - case TUSB_REQ_GET_STATUS: - { + case TUSB_REQ_GET_STATUS: { // Device status bit mask // - Bit 0: Self Powered // - Bit 1: Remote Wakeup enabled uint16_t status = (uint16_t) ((_usbd_dev.self_powered ? 1u : 0u) | (_usbd_dev.remote_wakeup_en ? 2u : 0u)); tud_control_xfer(rhport, p_request, &status, 2); + break; } - break; // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; @@ -753,8 +768,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; //------------- Class/Interface Specific Request -------------// - case TUSB_REQ_RCPT_INTERFACE: - { + case TUSB_REQ_RCPT_INTERFACE: { uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); @@ -763,25 +777,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) - { + if ( !invoke_class_control(rhport, driver, p_request) ) { // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - switch(p_request->bRequest) - { + switch(p_request->bRequest) { case TUSB_REQ_GET_INTERFACE: case TUSB_REQ_SET_INTERFACE: // Clear complete callback if driver set since it can also stall the request. usbd_control_set_complete_callback(NULL); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) - { + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) { uint8_t alternate = 0; tud_control_xfer(rhport, p_request, &alternate, 1); - }else - { + }else { tud_control_status(rhport, p_request); } break; @@ -789,54 +799,42 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const default: return false; } } + break; } - break; //------------- Endpoint Request -------------// - case TUSB_REQ_RCPT_ENDPOINT: - { + case TUSB_REQ_RCPT_ENDPOINT: { uint8_t const ep_addr = tu_u16_low(p_request->wIndex); uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Forward class request to its driver TU_VERIFY(driver); return invoke_class_control(rhport, driver, p_request); - } - else - { + } else { // Handle STD request to endpoint - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_STATUS: - { + switch ( p_request->bRequest ) { + case TUSB_REQ_GET_STATUS: { uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; tud_control_xfer(rhport, p_request, &status, 2); } break; case TUSB_REQ_CLEAR_FEATURE: - case TUSB_REQ_SET_FEATURE: - { - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) - { + case TUSB_REQ_SET_FEATURE: { + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) { + if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) { usbd_edpt_clear_stall(rhport, ep_addr); - }else - { + }else { usbd_edpt_stall(rhport, ep_addr); } } - if (driver) - { + if (driver) { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will also forward std request targeted endpoint to class drivers as well @@ -852,14 +850,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; + default: + TU_BREAKPOINT(); + return false; } } } break; // Unknown recipient - default: TU_BREAKPOINT(); return false; + default: + TU_BREAKPOINT(); + return false; } return true; @@ -913,7 +915,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) { // Open successfully - TU_LOG(USBD_DBG, " %s opened\r\n", driver->name); + TU_LOG_USBD(" %s opened\r\n", driver->name); // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or // BTH (even CDC) with class in device descriptor (single interface) @@ -956,9 +958,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); } - // invoke callback - if (tud_mount_cb) tud_mount_cb(); - return true; } @@ -972,7 +971,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { case TUSB_DESC_DEVICE: { - TU_LOG(USBD_DBG, " Device\r\n"); + TU_LOG_USBD(" Device\r\n"); void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); @@ -996,7 +995,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_BOS: { - TU_LOG(USBD_DBG, " BOS\r\n"); + TU_LOG_USBD(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; @@ -1018,12 +1017,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if ( desc_type == TUSB_DESC_CONFIGURATION ) { - TU_LOG(USBD_DBG, " Configuration[%u]\r\n", desc_index); + TU_LOG_USBD(" Configuration[%u]\r\n", desc_index); desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); }else { // Host only request this after getting Device Qualifier descriptor - TU_LOG(USBD_DBG, " Other Speed Configuration\r\n"); + TU_LOG_USBD(" Other Speed Configuration\r\n"); TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); } @@ -1039,7 +1038,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_STRING: { - TU_LOG(USBD_DBG, " String[%u]\r\n", desc_index); + TU_LOG_USBD(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); @@ -1052,7 +1051,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_DEVICE_QUALIFIER: { - TU_LOG(USBD_DBG, " Device Qualifier\r\n"); + TU_LOG_USBD(" Device Qualifier\r\n"); TU_VERIFY( tud_descriptor_device_qualifier_cb ); @@ -1071,66 +1070,69 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ -TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const * event, bool in_isr) -{ - switch (event->event_id) - { +TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) { + bool send = false; + switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - break; + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + send = true; + break; case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected - if ( _usbd_dev.connected ) - { + if (_usbd_dev.connected) { _usbd_dev.suspended = 1; - osal_queue_send(_usbd_q, event, in_isr); + send = true; } - break; + break; case DCD_EVENT_RESUME: // skip event if not connected (especially required for SAMD) - if ( _usbd_dev.connected ) - { + if (_usbd_dev.connected) { _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); + send = true; } - break; + break; case DCD_EVENT_SOF: - // SOF driver handler in ISR context - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if (driver && driver->sof) - { - driver->sof(event->rhport, event->sof.frame_count); - } - } - // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational - if ( _usbd_dev.suspended ) - { + if (_usbd_dev.suspended) { _usbd_dev.suspended = 0; - dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; - osal_queue_send(_usbd_q, &event_resume, in_isr); + dcd_event_t const event_resume = {.rhport = event->rhport, .event_id = DCD_EVENT_RESUME}; + queue_event(&event_resume, in_isr); + } + + // SOF driver handler in ISR context + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { + usbd_class_driver_t const* driver = get_driver(i); + if (driver && driver->sof) { + driver->sof(event->rhport, event->sof.frame_count); + } } // skip osal queue for SOF in usbd task - break; + break; + + case DCD_EVENT_SETUP_RECEIVED: + _usbd_dev.setup_count++; + send = true; + break; default: - osal_queue_send(_usbd_q, event, in_isr); - break; + send = true; + break; + } + + if (send) { + queue_event(event, in_isr); } } @@ -1174,26 +1176,22 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count } // Helper to defer an isr function -void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) -{ - dcd_event_t event = - { +void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) { + dcd_event_t event = { .rhport = 0, .event_id = USBD_EVENT_FUNC_CALL, }; - event.func_call.func = func; event.func_call.param = param; - dcd_event_handler(&event, in_isr); + queue_event(&event, in_isr); } //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); @@ -1202,59 +1200,59 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) return dcd_edpt_open(rhport, desc_ep); } -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; // TODO add this check later, also make sure we don't starve an out endpoint while suspending // TU_VERIFY(tud_ready()); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; return tu_edpt_claim(ep_state, _usbd_mutex); } -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; return tu_edpt_release(ep_state, _usbd_mutex); } -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // TODO skip ready() check for now since enumeration also use this API // TU_VERIFY(tud_ready()); - TU_LOG(USBD_DBG, " Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); + TU_LOG_USBD(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); +#if CFG_TUD_LOG_LEVEL >= 3 + if(dir == TUSB_DIR_IN) { + TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2); + } +#endif // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; - if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) - { + if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)) { return true; - }else - { + } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG(USBD_DBG, "FAILED\r\n"); + TU_LOG_USBD("FAILED\r\n"); TU_BREAKPOINT(); return false; } @@ -1264,117 +1262,100 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG(USBD_DBG, " Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG_USBD(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) - { - TU_LOG(USBD_DBG, "OK\r\n"); + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { + TU_LOG_USBD("OK\r\n"); return true; - }else - { + } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG(USBD_DBG, "failed\r\n"); + TU_LOG_USBD("failed\r\n"); TU_BREAKPOINT(); return false; } } -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); return _usbd_dev.ep_status[epnum][dir].busy; } -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // only stalled if currently cleared - if ( !_usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; - } + TU_LOG_USBD(" Stall EP %02X\r\n", ep_addr); + dcd_edpt_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = 1; + _usbd_dev.ep_status[epnum][dir].busy = 1; } -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // only clear if currently stalled - if ( _usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - } + TU_LOG_USBD(" Clear Stall EP %02X\r\n", ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; } -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); return _usbd_dev.ep_status[epnum][dir].stalled; } /** * usbd_edpt_close will disable an endpoint. - * * In progress transfers on this EP may be delivered after this call. - * */ -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { rhport = _usbd_rhport; TU_ASSERT(dcd_edpt_close, /**/); - TU_LOG(USBD_DBG, " CLOSING Endpoint: 0x%02X\r\n", ep_addr); + TU_LOG_USBD(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return; } -void usbd_sof_enable(uint8_t rhport, bool en) -{ +void usbd_sof_enable(uint8_t rhport, bool en) { rhport = _usbd_rhport; // TODO: Check needed if all drivers including the user sof_cb does not need an active SOF ISR any more. @@ -1382,8 +1363,7 @@ void usbd_sof_enable(uint8_t rhport, bool en) dcd_sof_enable(rhport, en); } -bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) -{ +bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { rhport = _usbd_rhport; TU_ASSERT(dcd_edpt_iso_alloc); @@ -1392,20 +1372,19 @@ bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packe return dcd_edpt_iso_alloc(rhport, ep_addr, largest_packet_size); } -bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ +bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(desc_ep->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(dcd_edpt_iso_activate); TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return dcd_edpt_iso_activate(rhport, desc_ep); } diff --git a/test-devices/loopback-stm32/lib/tinyusb/device/usbd.h b/test-devices/loopback-stm32/lib/tinyusb/device/usbd.h index 255e5a84..f3673404 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/device/usbd.h +++ b/test-devices/loopback-stm32/lib/tinyusb/device/usbd.h @@ -37,9 +37,12 @@ extern "C" { // Application API //--------------------------------------------------------------------+ -// Init device stack +// Init device stack on roothub port bool tud_init (uint8_t rhport); +// Deinit device stack on roothub port +bool tud_deinit(uint8_t rhport); + // Check if device stack is already initialized bool tud_inited(void); @@ -50,8 +53,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop TU_ATTR_ALWAYS_INLINE static inline -void tud_task (void) -{ +void tud_task (void) { tud_task_ext(UINT32_MAX, false); } @@ -80,8 +82,7 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } @@ -148,6 +149,9 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); // Invoked when usb bus is resumed TU_ATTR_WEAK void tud_resume_cb(void); +// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext() +void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); + // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); @@ -217,8 +221,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC Call */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC ACM: support line request + send break */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 6,\ /* CDC Union */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ /* Endpoint Notification */\ @@ -347,8 +351,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 -#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx +#define TUD_AUDIO_DESC_IAD(_firstitf, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitf, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 @@ -392,6 +396,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // For more channels, add definitions here +/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */ +#define TUD_AUDIO_DESC_STD_AC_INT_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AC_INT_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval + /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ @@ -420,7 +429,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source @@ -443,7 +452,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -467,7 +476,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) @@ -492,7 +501,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -516,7 +525,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) @@ -540,7 +549,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ @@ -564,7 +573,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ @@ -773,10 +782,6 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 #define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -#define CFG_TUD_BTH_ISO_ALT_COUNT 0 -#endif - // Length of template descriptor: 38 bytes + number of ISO alternatives * 23 #define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) diff --git a/test-devices/loopback-stm32/lib/tinyusb/device/usbd_control.c b/test-devices/loopback-stm32/lib/tinyusb/device/usbd_control.c index ea8eef28..35cce1f7 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/device/usbd_control.c +++ b/test-devices/loopback-stm32/lib/tinyusb/device/usbd_control.c @@ -32,30 +32,38 @@ #include "tusb.h" #include "device/usbd_pvt.h" -#if CFG_TUSB_DEBUG >= 2 +//--------------------------------------------------------------------+ +// Callback weak stubs (called if application does not provide) +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) { + (void) rhport; + (void) request; +} + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif -enum -{ +enum { EDPT_CTRL_OUT = 0x00, - EDPT_CTRL_IN = 0x80 + EDPT_CTRL_IN = 0x80 }; -typedef struct -{ +typedef struct { tusb_control_request_t request; - uint8_t* buffer; uint16_t data_len; uint16_t total_xferred; - usbd_control_xfer_cb_t complete_cb; } usbd_control_xfer_t; tu_static usbd_control_xfer_t _ctrl_xfer; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ @@ -63,20 +71,18 @@ tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ // Queue ZLP status transaction -static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) -{ +static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const* request) { // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; +bool tud_control_status(uint8_t rhport, tusb_control_request_t const* request) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; + _ctrl_xfer.data_len = 0; return _status_stage_xact(rhport, request); } @@ -84,16 +90,15 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) // Queue a transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet -static bool _data_stage_xact(uint8_t rhport) -{ - uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); +static bool _data_stage_xact(uint8_t rhport) { + uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, + CFG_TUD_ENDPOINT0_SIZE); uint8_t ep_addr = EDPT_CTRL_OUT; - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) - { + if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { ep_addr = EDPT_CTRL_IN; - if ( xact_len ) { + if (xact_len) { TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); } } @@ -103,29 +108,24 @@ static bool _data_stage_xact(uint8_t rhport) // Transmit data to/from the control endpoint. // If the request's wLength is zero, a status packet is sent instead. -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = (uint8_t*) buffer; +bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, void* buffer, uint16_t len) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = (uint8_t*) buffer; _ctrl_xfer.total_xferred = 0U; - _ctrl_xfer.data_len = tu_min16(len, request->wLength); + _ctrl_xfer.data_len = tu_min16(len, request->wLength); - if (request->wLength > 0U) - { - if(_ctrl_xfer.data_len > 0U) - { + if (request->wLength > 0U) { + if (_ctrl_xfer.data_len > 0U) { TU_ASSERT(buffer); } // TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); // Data stage - TU_ASSERT( _data_stage_xact(rhport) ); - } - else - { + TU_ASSERT(_data_stage_xact(rhport)); + } else { // Status stage - TU_ASSERT( _status_stage_xact(rhport, request) ); + TU_ASSERT(_status_stage_xact(rhport, request)); } return true; @@ -134,49 +134,42 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo //--------------------------------------------------------------------+ // USBD API //--------------------------------------------------------------------+ - void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void usbd_control_set_request(tusb_control_request_t const* request); +void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp); +bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void usbd_control_reset(void) -{ +void usbd_control_reset(void) { tu_varclr(&_ctrl_xfer); } // Set complete callback -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) -{ +void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) { _ctrl_xfer.complete_cb = fp; } // for dcd_set_address where DCD is responsible for status response -void usbd_control_set_request(tusb_control_request_t const *request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; +void usbd_control_set_request(tusb_control_request_t const* request) { + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; + _ctrl_xfer.data_len = 0; } // callback when a transaction complete on // - DATA stage of control endpoint or // - Status stage -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; // Endpoint Address is opposite to direction bit, this is Status Stage complete event - if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) - { + if (tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction) { TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - if (_ctrl_xfer.complete_cb) - { + if (_ctrl_xfer.complete_cb) { // TODO refactor with usbd_driver_print_control_complete_name _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); } @@ -184,11 +177,10 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result return true; } - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) - { + if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); + TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += (uint16_t) xferred_bytes; @@ -196,37 +188,32 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // Data Stage is complete when all request's length are transferred or // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) - { + if ((_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || + (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE)) { // DATA stage is complete bool is_ok = true; // invoke complete callback if set // callback can still stall control in status phase e.g out data does not make sense - if ( _ctrl_xfer.complete_cb ) - { - #if CFG_TUSB_DEBUG >= 2 + if (_ctrl_xfer.complete_cb) { + #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); } - if ( is_ok ) - { + if (is_ok) { // Send status - TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); - }else - { + TU_ASSERT(_status_stage_xact(rhport, &_ctrl_xfer.request)); + } else { // Stall both IN and OUT control endpoint dcd_edpt_stall(rhport, EDPT_CTRL_OUT); dcd_edpt_stall(rhport, EDPT_CTRL_IN); } - } - else - { + } else { // More data to transfer - TU_ASSERT( _data_stage_xact(rhport) ); + TU_ASSERT(_data_stage_xact(rhport)); } return true; diff --git a/test-devices/loopback-stm32/lib/tinyusb/device/usbd_pvt.h b/test-devices/loopback-stm32/lib/tinyusb/device/usbd_pvt.h index 8393d346..47752f32 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/device/usbd_pvt.h +++ b/test-devices/loopback-stm32/lib/tinyusb/device/usbd_pvt.h @@ -23,8 +23,8 @@ * * This file is part of the TinyUSB stack. */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ +#ifndef _TUSB_USBD_PVT_H_ +#define _TUSB_USBD_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -33,17 +33,19 @@ extern "C" { #endif +#define TU_LOG_USBD(...) TU_LOG(CFG_TUD_LOG_LEVEL, __VA_ARGS__) + //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 +typedef struct { + #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* name; #endif void (* init ) (void); + bool (* deinit ) (void); void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); @@ -52,7 +54,7 @@ typedef struct } usbd_class_driver_t; // Invoked when initializing device stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. +// Can be implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; @@ -104,8 +106,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline -bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); } @@ -117,11 +118,10 @@ void usbd_sof_enable(uint8_t rhport, bool en); *------------------------------------------------------------------*/ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - +void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); #ifdef __cplusplus } #endif -#endif /* USBD_PVT_H_ */ +#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/hwcfg_list.md b/test-devices/loopback-stm32/lib/tinyusb/dwc2/hwcfg_list.md deleted file mode 100644 index b5590da0..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/dwc2/hwcfg_list.md +++ /dev/null @@ -1,777 +0,0 @@ -# DWC2 Hardware Configuration Registers - -## Broadcom BCM2711 (Pi4) - -dwc2->guid = 2708A000 -dwc2->gsnpsid = 4F54280A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228DDD50 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 1 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 7 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = FF000E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 4080 - -dwc2->ghwcfg4 = 1FF00020 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 0 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 15 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## EFM32GG FS - -dwc2->guid = 0 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228F5910 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 13 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 1F204E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 1 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 498 - -dwc2->ghwcfg4 = 1BF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## ESP32-S2 Fullspeed - -dwc2->guid = 0 -dwc2->gsnpsid = 4F54400A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 224DD930 -hw_cfg2->op_mode = 2 -hw_cfg2->arch = 3 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 1 -hw_cfg2->fs_phy_type = 2 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 9 -hw_cfg2->period_channel_support = 0 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 1 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 22 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = C804B5 -hw_cfg3->xfer_size_width = 10 -hw_cfg3->packet_size_width = 5 -hw_cfg3->otg_enable = 0 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 1 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 23130 - -dwc2->ghwcfg4 = D3F0A030 -hw_cfg4->num_dev_period_in_ep = 10 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 0 -hw_cfg4->hibernation = 1 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 1 -hw_cfg4->acg_enable = 1 -hw_cfg4->utmi_phy_data_width = 1 -hw_cfg4->dev_ctrl_ep_num = 10 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 0 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 0 -hw_cfg4->dedicated_fifos = 0 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 1 - -## STM32F407 and STM32F207 - -STM32F407 and STM32F207 are exactly the same - -### STM32F407 Fullspeed - -dwc2->guid = 1200 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229DCD20 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 3 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 20001E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = FF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 7 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -### STM32F407 Highspeed - -dwc2->guid = 1100 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED590 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 2 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3F403E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 1012 - -dwc2->ghwcfg4 = 17F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F411 Fullspeed - -dwc2->guid = 1200 -dwc2->gsnpsid = 4F54281A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229DCD20 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 3 -hw_cfg2->num_host_ch = 7 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 20001E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = FF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 7 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F412 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54320A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F723 - -### STM32F723 HighSpeed - -dwc2->guid = 3100 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229FE1D0 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 3 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 8 -hw_cfg2->num_host_ch = 15 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3EED2E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 1006 - -dwc2->ghwcfg4 = 23F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 1 -hw_cfg4->dma_desc_enable = 1 -hw_cfg4->dma_dynamic = 0 - -### STM32F723 Fullspeed - -dwc2->guid = 3000 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32F767 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54320A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## STM32H743 (both cores HS) - -dwc2->guid = 2300 -dwc2->gsnpsid = 4F54330A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229FE190 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 2 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 8 -hw_cfg2->num_host_ch = 15 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 3B8D2E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 1 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 952 - -dwc2->ghwcfg4 = E3F00030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 1 -hw_cfg4->dma_desc_enable = 1 -hw_cfg4->dma_dynamic = 1 - -## STM32L476 FS - -dwc2->guid = 2000 -dwc2->gsnpsid = 4F54310A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 229ED520 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 5 -hw_cfg2->num_host_ch = 11 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 1 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 200D1E8 -hw_cfg3->xfer_size_width = 8 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 1 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 1 -hw_cfg3->lpm_mode = 1 -hw_cfg3->total_fifo_size = 512 - -dwc2->ghwcfg4 = 17F08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 11 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## GD32VF103 Fullspeed - -dwc2->guid = 1000 -dwc2->gsnpsid = 0 -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 0 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 0 -hw_cfg2->point2point = 0 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 0 -hw_cfg2->num_dev_ep = 0 -hw_cfg2->num_host_ch = 0 -hw_cfg2->period_channel_support = 0 -hw_cfg2->enable_dynamic_fifo = 0 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 0 -hw_cfg2->host_period_tx_q_depth = 0 -hw_cfg2->dev_token_q_depth = 0 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 0 -hw_cfg3->xfer_size_width = 0 -hw_cfg3->packet_size_width = 0 -hw_cfg3->otg_enable = 0 -hw_cfg3->i2c_enable = 0 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 0 - -dwc2->ghwcfg4 = 0 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 0 -hw_cfg4->ahb_freq_min = 0 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 0 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 0 -hw_cfg4->vbus_valid_filter_enabled = 0 -hw_cfg4->a_valid_filter_enabled = 0 -hw_cfg4->b_valid_filter_enabled = 0 -hw_cfg4->dedicated_fifos = 0 -hw_cfg4->num_dev_in_eps = 0 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 0 - -## XMC4500 - -dwc2->guid = AEC000 -dwc2->gsnpsid = 4F54292A -dwc2->ghwcfg1 = 0 - -dwc2->ghwcfg2 = 228F5930 -hw_cfg2->op_mode = 0 -hw_cfg2->arch = 2 -hw_cfg2->point2point = 1 -hw_cfg2->hs_phy_type = 0 -hw_cfg2->fs_phy_type = 1 -hw_cfg2->num_dev_ep = 6 -hw_cfg2->num_host_ch = 13 -hw_cfg2->period_channel_support = 1 -hw_cfg2->enable_dynamic_fifo = 1 -hw_cfg2->mul_cpu_int = 0 -hw_cfg2->nperiod_tx_q_depth = 2 -hw_cfg2->host_period_tx_q_depth = 2 -hw_cfg2->dev_token_q_depth = 8 -hw_cfg2->otg_enable_ic_usb = 0 - -dwc2->ghwcfg3 = 27A01E5 -hw_cfg3->xfer_size_width = 5 -hw_cfg3->packet_size_width = 6 -hw_cfg3->otg_enable = 1 -hw_cfg3->i2c_enable = 1 -hw_cfg3->vendor_ctrl_itf = 0 -hw_cfg3->optional_feature_removed = 0 -hw_cfg3->synch_reset = 0 -hw_cfg3->otg_adp_support = 0 -hw_cfg3->otg_enable_hsic = 0 -hw_cfg3->battery_charger_support = 0 -hw_cfg3->lpm_mode = 0 -hw_cfg3->total_fifo_size = 634 - -dwc2->ghwcfg4 = DBF08030 -hw_cfg4->num_dev_period_in_ep = 0 -hw_cfg4->power_optimized = 1 -hw_cfg4->ahb_freq_min = 1 -hw_cfg4->hibernation = 0 -hw_cfg4->service_interval_mode = 0 -hw_cfg4->ipg_isoc_en = 0 -hw_cfg4->acg_enable = 0 -hw_cfg4->utmi_phy_data_width = 2 -hw_cfg4->dev_ctrl_ep_num = 0 -hw_cfg4->iddg_filter_enabled = 1 -hw_cfg4->vbus_valid_filter_enabled = 1 -hw_cfg4->a_valid_filter_enabled = 1 -hw_cfg4->b_valid_filter_enabled = 1 -hw_cfg4->dedicated_fifos = 1 -hw_cfg4->num_dev_in_eps = 13 -hw_cfg4->dma_desc_enable = 0 -hw_cfg4->dma_dynamic = 1 diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal.h index f092e8ff..8f45ea5c 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal.h +++ b/test-devices/loopback-stm32/lib/tinyusb/osal/osal.h @@ -74,15 +74,18 @@ typedef void (*osal_task_func_t)( void * ); // Should be implemented as static inline function in osal_port.h header /* osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); + bool osal_semaphore_delete(osal_semaphore_t semd_hdl); bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); + bool osal_mutex_delete(osal_mutex_t mutex_hdl) bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); bool osal_mutex_unlock(osal_mutex_t mutex_hdl); osal_queue_t osal_queue_create(osal_queue_def_t* qdef); + bool osal_queue_delete(osal_queue_t qhdl); bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec); bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); bool osal_queue_empty(osal_queue_t qhdl); diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_freertos.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_freertos.h deleted file mode 100644 index 477f6489..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_freertos.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_FREERTOS_H_ -#define _TUSB_OSAL_FREERTOS_H_ - -// FreeRTOS Headers -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -#if configSUPPORT_STATIC_ALLOCATION - typedef StaticSemaphore_t osal_semaphore_def_t; - typedef StaticSemaphore_t osal_mutex_def_t; -#else - // not used therefore defined to smallest possible type to save space - typedef uint8_t osal_semaphore_def_t; - typedef uint8_t osal_mutex_def_t; -#endif - -typedef SemaphoreHandle_t osal_semaphore_t; -typedef SemaphoreHandle_t osal_mutex_t; - -// _int_set is not used with an RTOS -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; -#if configSUPPORT_STATIC_ALLOCATION - StaticQueue_t sq; -#endif -}osal_queue_def_t; - -typedef QueueHandle_t osal_queue_t; - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) -{ - if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY; - if (msec == 0) return 0; - - uint32_t ticks = pdMS_TO_TICKS(msec); - - // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms - // we still need to delay at least 1 tick - if (ticks == 0) ticks =1 ; - - return ticks; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - vTaskDelay( pdMS_TO_TICKS(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xSemaphoreCreateBinaryStatic(semdef); -#else - (void) semdef; - return xSemaphoreCreateBinary(); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - if ( !in_isr ) - { - return xSemaphoreGive(sem_hdl) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec)); -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) -{ - xQueueReset(sem_hdl); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xSemaphoreCreateMutexStatic(mdef); -#else - (void) mdef; - return xSemaphoreCreateMutex(); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return xSemaphoreGive(mutex_hdl); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ -#if configSUPPORT_STATIC_ALLOCATION - return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -#else - return xQueueCreate(qdef->depth, qdef->item_sz); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - return xQueueReceive(qhdl, data, _osal_ms2tick(msec)); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if ( !in_isr ) - { - return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return uxQueueMessagesWaiting(qhdl) == 0; -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_mynewt.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_mynewt.h deleted file mode 100644 index b8ea2087..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_mynewt.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef OSAL_MYNEWT_H_ -#define OSAL_MYNEWT_H_ - -#include "os/os.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - os_time_delay( os_time_ms_to_ticks32(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct os_sem osal_semaphore_def_t; -typedef struct os_sem* osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - return os_sem_release(sem_hdl) == OS_OK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_sem_pend(sem_hdl, ticks) == OS_OK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - // TODO implement later -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct os_mutex osal_mutex_def_t; -typedef struct os_mutex* osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_mutex_pend(mutex_hdl, ticks) == OS_OK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mutex_release(mutex_hdl) == OS_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - static struct os_event _name##_##evbuf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - void* evbuf; - - struct os_mempool mpool; - struct os_mempool epool; - - struct os_eventq evq; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; - if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; - - os_eventq_init(&qdef->evq); - return (osal_queue_t) qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - (void) msec; // os_eventq_get() does not take timeout, always behave as msec = WAIT_FOREVER - - struct os_event* ev; - ev = os_eventq_get(&qhdl->evq); - - memcpy(data, ev->ev_arg, qhdl->item_sz); // copy message - os_memblock_put(&qhdl->mpool, ev->ev_arg); // put back mem block - os_memblock_put(&qhdl->epool, ev); // put back ev block - - return true; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - (void) in_isr; - - // get a block from mem pool for data - void* ptr = os_memblock_get(&qhdl->mpool); - if (!ptr) return false; - memcpy(ptr, data, qhdl->item_sz); - - // get a block from event pool to put into queue - struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool); - if (!ev) - { - os_memblock_put(&qhdl->mpool, ptr); - return false; - } - tu_memclr(ev, sizeof(struct os_event)); - ev->ev_arg = ptr; - - os_eventq_put(&qhdl->evq, ev); - - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return STAILQ_EMPTY(&qhdl->evq.evq_list); -} - - -#ifdef __cplusplus - } -#endif - -#endif /* OSAL_MYNEWT_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_none.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_none.h index 5f407378..c93f7a86 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_none.h +++ b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_none.h @@ -24,11 +24,11 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OSAL_NONE_H_ -#define _TUSB_OSAL_NONE_H_ +#ifndef TUSB_OSAL_NONE_H_ +#define TUSB_OSAL_NONE_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ @@ -37,45 +37,46 @@ #if CFG_TUH_ENABLED // currently only needed/available in host mode -void osal_task_delay(uint32_t msec); +TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { volatile uint16_t count; -}osal_semaphore_def_t; +} osal_semaphore_def_t; typedef osal_semaphore_def_t* osal_semaphore_t; -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { semdef->count = 0; return semdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { + (void) semd_hdl; + return true; // nothing to do +} + + +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; sem_hdl->count++; return true; } // TODO blocking for now -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { (void) msec; - while (sem_hdl->count == 0) { } + while (sem_hdl->count == 0) {} sem_hdl->count--; return true; } -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) { sem_hdl->count = 0; } @@ -90,19 +91,21 @@ typedef osal_semaphore_t osal_mutex_t; // Note: multiple cores MCUs usually do provide IPC API for mutex // or we can use std atomic function -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { mdef->count = 1; return mdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { + (void) mutex_hdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { return osal_semaphore_wait(mutex_hdl, msec); } -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return osal_semaphore_post(mutex_hdl, false); } @@ -119,11 +122,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd //--------------------------------------------------------------------+ #include "common/tusb_fifo.h" -typedef struct -{ - void (*interrupt_set)(bool); +typedef struct { + void (* interrupt_set)(bool); tu_fifo_t ff; -}osal_queue_def_t; +} osal_queue_def_t; typedef osal_queue_def_t* osal_queue_t; @@ -136,27 +138,28 @@ typedef osal_queue_def_t* osal_queue_t; } // lock queue by disable USB interrupt -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) { // disable dcd/hcd interrupt qhdl->interrupt_set(false); } // unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { // enable dcd/hcd interrupt qhdl->interrupt_set(true); } -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { + (void) qhdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { (void) msec; // not used, always behave as msec = 0 _osal_q_lock(qhdl); @@ -166,8 +169,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { if (!in_isr) { _osal_q_lock(qhdl); } @@ -178,20 +180,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void _osal_q_unlock(qhdl); } - TU_ASSERT(success); - return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { // Skip queue lock/unlock since this function is primarily called // with interrupt disabled before going into low power mode return tu_fifo_empty(&qhdl->ff); } #ifdef __cplusplus - } +} #endif -#endif /* _TUSB_OSAL_NONE_H_ */ +#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_pico.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_pico.h deleted file mode 100644 index e6efa096..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_pico.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_PICO_H_ -#define _TUSB_OSAL_PICO_H_ - -#include "pico/time.h" -#include "pico/sem.h" -#include "pico/mutex.h" -#include "pico/critical_section.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - sleep_ms(msec); -} - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - sem_init(semdef, 0, 255); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_release(sem_hdl); - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - return sem_acquire_timeout_ms(sem_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_reset(sem_hdl, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, *osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mutex_init(mdef); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return mutex_enter_timeout_ms(mutex_hdl, msec); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - mutex_exit(mutex_hdl); - return true; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -typedef struct -{ - tu_fifo_t ff; - struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section -} osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) -{ - critical_section_enter_blocking(&qhdl->critsec); -} - -// unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - critical_section_exit(&qhdl->critsec); -} - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - critical_section_init(&qdef->critsec); - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - (void) msec; // not used, always behave as msec = 0 - - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - (void) in_isr; - - _osal_q_lock(qhdl); - bool success = tu_fifo_write(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - TU_ASSERT(success); - - return success; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single - // volatile read. - - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtthread.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtthread.h deleted file mode 100644 index 18eb9c69..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtthread.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 tfx2001 (2479727366@qq.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTTHREAD_H_ -#define _TUSB_OSAL_RTTHREAD_H_ - -// RT-Thread Headers -#include "rtthread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { - rt_thread_mdelay(msec); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct rt_semaphore osal_semaphore_def_t; -typedef rt_sem_t osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t -osal_semaphore_create(osal_semaphore_def_t *semdef) { - rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; - return rt_sem_release(sem_hdl) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { - return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct rt_mutex osal_mutex_def_t; -typedef rt_mutex_t osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { - rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { - return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { - return rt_mutex_release(mutex_hdl) == RT_EOK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - static _type _name##_##buf[_depth]; \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct { - uint16_t depth; - uint16_t item_sz; - void *buf; - - struct rt_messagequeue sq; -} osal_queue_def_t; - -typedef rt_mq_t osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { - rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, - qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO); - return &(qdef->sq); -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { - - rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec); - return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - (void) in_isr; - return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { - return (qhdl->entry) == 0; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtx4.h b/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtx4.h deleted file mode 100644 index e443135e..00000000 --- a/test-devices/loopback-stm32/lib/tinyusb/osal/osal_rtx4.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Tian Yunhao (t123yh) - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTX4_H_ -#define _TUSB_OSAL_RTX4_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) -{ - uint16_t hi = msec >> 16; - uint16_t lo = msec; - while (hi--) { - os_dly_wait(0xFFFE); - } - os_dly_wait(lo); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { - if (msec == OSAL_TIMEOUT_WAIT_FOREVER) - return 0xFFFF; - else if (msec >= 0xFFFE) - return 0xFFFE; - else - return msec; -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef OS_SEM osal_semaphore_def_t; -typedef OS_ID osal_semaphore_t; - -TU_ATTR_ALWAYS_INLINE static inline OS_ID osal_semaphore_create(osal_semaphore_def_t* semdef) { - os_sem_init(semdef, 0); - return semdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - if ( !in_isr ) { - os_sem_send(sem_hdl); - } else { - isr_sem_send(sem_hdl); - } - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { - return os_sem_wait(sem_hdl, msec2wait(msec)) != OS_R_TMO; -} - -TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - // TODO: implement -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef OS_MUT osal_mutex_def_t; -typedef OS_ID osal_mutex_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - os_mut_init(mdef); - return mdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mut_release(mutex_hdl) == OS_R_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - os_mbx_declare(_name##__mbox, _depth); \ - _declare_box(_name##__pool, sizeof(_type), _depth); \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .pool = _name##__pool, .mbox = _name##__mbox }; - - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - U32* pool; - U32* mbox; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4); - _init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz); - return qdef; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) -{ - void* buf; - os_mbx_wait(qhdl->mbox, &buf, msec2wait(msec)); - memcpy(data, buf, qhdl->item_sz); - _free_box(qhdl->pool, buf); - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - void* buf = _alloc_box(qhdl->pool); - memcpy(buf, data, qhdl->item_sz); - if ( !in_isr ) - { - os_mbx_send(qhdl->mbox, buf, 0xFFFF); - } - else - { - isr_mbx_send(qhdl->mbox, buf); - } - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return os_mbx_check(qhdl->mbox) == qhdl->depth; -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c b/test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c similarity index 53% rename from test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c rename to test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 30a2e9c8..a26c6689 100644 --- a/test-devices/composite-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev.c +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -44,6 +44,7 @@ * L0x2, L0x3 1024 byte buffer * L1 512 byte buffer * L4x2, L4x3 1024 byte buffer + * G0 2048 byte buffer * * To use this driver, you must: * - If you are using a device with crystal-less USB, set up the clock recovery system (CRS) @@ -106,9 +107,9 @@ #include "device/dcd.h" #ifdef TUP_USBIP_FSDEV_STM32 - // Undefine to reduce the dependence on HAL - #undef USE_HAL_DRIVER - #include "dcd_stm32_fsdev_pvt_st.h" +// Undefine to reduce the dependence on HAL +#undef USE_HAL_DRIVER +#include "portable/st/stm32_fsdev/dcd_stm32_fsdev.h" #endif /***************************************************** @@ -118,17 +119,17 @@ // HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM // (8u here would mean 8 IN and 8 OUT) #ifndef MAX_EP_COUNT -# define MAX_EP_COUNT 8U +#define MAX_EP_COUNT 8U #endif // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef DCD_STM32_BTABLE_BASE -# define DCD_STM32_BTABLE_BASE 0U +#define DCD_STM32_BTABLE_BASE 0U #endif -#ifndef DCD_STM32_BTABLE_LENGTH -# define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) +#ifndef DCD_STM32_BTABLE_SIZE +#define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE) #endif /*************************************************** @@ -136,7 +137,7 @@ */ TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT, "Only 8 endpoints supported on the hardware"); -TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LENGTH), "BTABLE does not fit in PMA RAM"); +TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_SIZE)) <= (FSDEV_PMA_SIZE), "BTABLE does not fit in PMA RAM"); TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); //--------------------------------------------------------------------+ @@ -144,21 +145,18 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne //--------------------------------------------------------------------+ // One of these for every EP IN & OUT, uses a bit of RAM.... -typedef struct -{ - uint8_t * buffer; - tu_fifo_t * ff; +typedef struct { + uint8_t *buffer; + tu_fifo_t *ff; uint16_t total_len; uint16_t queued_len; - uint16_t pma_ptr; uint16_t max_packet_size; - uint16_t pma_alloc_size; - uint8_t ep_idx; // index for USB_EPnR register + uint8_t ep_idx; // index for USB_EPnR register + bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask } xfer_ctl_t; // EP allocator -typedef struct -{ +typedef struct { uint8_t ep_num; uint8_t ep_type; bool allocated[2]; @@ -178,28 +176,25 @@ static uint8_t remoteWakeCountdown; // When wake is requested // into the stack. static void dcd_handle_bus_reset(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix); +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); +static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr); static void dcd_ep_ctr_handler(void); // PMA allocation/access -static uint8_t open_ep_count; static uint16_t ep_buf_ptr; ///< Points to first free memory location -static void dcd_pma_alloc_reset(void); -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length); -static void dcd_pma_free(uint8_t ep_addr); -static void dcd_ep_free(uint8_t ep_addr); +static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes); +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes); -static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); -static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); +static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); +static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); //--------------------------------------------------------------------+ // Inline helper //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) +TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint32_t ep_addr) { uint8_t epnum = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); @@ -209,22 +204,11 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) return &xfer_status[epnum][dir]; } -// Using a function due to better type checks -// This seems better than having to do type casts everywhere else -TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { - *reg = (uint16_t)(*reg & ~mask); -} - -// Bits in ISTR are cleared upon writing 0 -TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint16_t mask) { - USB->ISTR = ~mask; -} - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -void dcd_init (uint8_t rhport) +void dcd_init(uint8_t rhport) { /* Clocks should already be enabled */ /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ @@ -232,40 +216,41 @@ void dcd_init (uint8_t rhport) /* The RM mentions to use a special ordering of PDWN and FRES, but this isn't done in HAL. * Here, the RM is followed. */ - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } - reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown + + USB->CNTR &= ~USB_CNTR_PDWN; + // Wait startup time, for F042 and F070, this is <= 1 us. - for(uint32_t i = 0; i<200; i++) // should be a few us - { + for (uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } USB->CNTR = 0; // Enable USB +#if !defined(STM32G0) && !defined(STM32H5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address USB->BTABLE = DCD_STM32_BTABLE_BASE; - +#endif USB->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled - for(uint32_t i=0; iCNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); // Enable pull-up if supported - if ( dcd_connect ) dcd_connect(rhport); + if (dcd_connect) { + dcd_connect(rhport); + } } // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. @@ -274,14 +259,14 @@ void dcd_init (uint8_t rhport) // Disable internal D+ PU void dcd_disconnect(uint8_t rhport) { - (void) rhport; + (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } // Enable internal D+ PU void dcd_connect(uint8_t rhport) { - (void) rhport; + (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } @@ -289,60 +274,54 @@ void dcd_connect(uint8_t rhport) // Disable internal D+ PU void dcd_disconnect(uint8_t rhport) { - (void) rhport; + (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } // Enable internal D+ PU void dcd_connect(uint8_t rhport) { - (void) rhport; + (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } #endif void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; - (void) en; + (void)rhport; + (void)en; - if (en) - { + if (en) { USB->CNTR |= USB_CNTR_SOFM; - } - else - { - USB->CNTR &= (uint16_t) ~USB_CNTR_SOFM; + } else { + USB->CNTR &= ~USB_CNTR_SOFM; } } // Enable device interrupt -void dcd_int_enable (uint8_t rhport) +void dcd_int_enable(uint8_t rhport) { (void)rhport; // Member here forces write to RAM before allowing ISR to execute __DSB(); __ISB(); -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || \ - CFG_TUSB_MCU == OPT_MCU_STM32L4 +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4 NVIC_EnableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 NVIC_EnableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to enable the right IRQs. - #ifdef SYSCFG_CFGR1_USB_IT_RMP - if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) - { +// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from +// shared USB/CAN IRQs to separate CAN and USB IRQs. +// This dynamically checks if this remap is active to enable the right IRQs. +#ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); - } - else - #endif + } else +#endif { NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); @@ -358,6 +337,16 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 +#ifdef STM32G0B0xx + NVIC_EnableIRQ(USB_IRQn); +#else + NVIC_EnableIRQ(USB_UCPD1_2_IRQn); +#endif + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + NVIC_EnableIRQ(USB_DRD_FS_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); @@ -366,7 +355,7 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_FS_IRQn); #else - #error Unknown arch in USB driver +#error Unknown arch in USB driver #endif } @@ -375,24 +364,21 @@ void dcd_int_disable(uint8_t rhport) { (void)rhport; -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || \ - CFG_TUSB_MCU == OPT_MCU_STM32L4 +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4 NVIC_DisableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 NVIC_DisableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to disable the right IRQs. - #ifdef SYSCFG_CFGR1_USB_IT_RMP - if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) - { +// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from +// shared USB/CAN IRQs to separate CAN and USB IRQs. +// This dynamically checks if this remap is active to disable the right IRQs. +#ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); - } - else - #endif + } else +#endif { NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn); NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn); @@ -408,6 +394,16 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 +#ifdef STM32G0B0xx + NVIC_DisableIRQ(USB_IRQn); +#else + NVIC_DisableIRQ(USB_UCPD1_2_IRQn); +#endif + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + NVIC_DisableIRQ(USB_DRD_FS_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); @@ -416,7 +412,7 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_FS_IRQn); #else - #error Unknown arch in USB driver +#error Unknown arch in USB driver #endif // CMSIS has a membar after disabling interrupts @@ -425,8 +421,8 @@ void dcd_int_disable(uint8_t rhport) // Receive Set Address request, mcu port must also include status IN response void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - (void) dev_addr; + (void)rhport; + (void)dev_addr; // Respond with status dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0); @@ -437,45 +433,35 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; + (void)rhport; - USB->CNTR |= (uint16_t) USB_CNTR_RESUME; + USB->CNTR |= USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } -static const tusb_desc_endpoint_t ep0OUT_desc = -{ - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = 0x00, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 +static const tusb_desc_endpoint_t ep0OUT_desc = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0x00, + .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, + .bInterval = 0 }; -static const tusb_desc_endpoint_t ep0IN_desc = -{ - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = 0x80, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 +static const tusb_desc_endpoint_t ep0IN_desc = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0x80, + .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, + .bInterval = 0 }; static void dcd_handle_bus_reset(void) { - //__IO uint16_t * const epreg = &(EPREG(0)); USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag - - for(uint32_t i=0; iDADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. } @@ -501,30 +489,63 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) // Verify the CTR_TX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? - if((wEPRegVal & USB_EP_CTR_TX) == 0U) - { + if ((wEPRegVal & USB_EP_CTR_TX) == 0U) { return; } /* clear int flag */ pcd_clear_tx_ep_ctr(USB, EPindex); - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); - if((xfer->total_len != xfer->queued_len)) /* TX not complete */ - { - dcd_transmit_packet(xfer, EPindex); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + + if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + // Ignore spurious interrupts that we don't schedule + // host can send IN token while there is no data to send, since ISO does not have NAK + // this will result to zero length packet --> trigger interrupt (which cannot be masked) + if (!xfer->iso_in_sending) { + return; + } + xfer->iso_in_sending = false; + + if (wEPRegVal & USB_EP_DTOG_TX) { + pcd_set_ep_tx_dbuf0_cnt(USB, EPindex, 0); + } else { + pcd_set_ep_tx_dbuf1_cnt(USB, EPindex, 0); + } } - else /* TX Complete */ - { + + if ((xfer->total_len != xfer->queued_len)) { + dcd_transmit_packet(xfer, EPindex); + } else { dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); } } // Handle CTR interrupt for the RX/OUT direction -// // Upon call, (wIstr & USB_ISTR_DIR) == 0U static void dcd_ep_ctr_rx_handler(uint32_t wIstr) { +#ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata also seems to apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } +#endif + uint32_t EPindex = wIstr & USB_ISTR_EP_ID; uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD; @@ -533,92 +554,83 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? - if((wEPRegVal & USB_EP_CTR_RX) == 0U) - { + if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { return; } - if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */ - { - // The setup_received function uses memcpy, so this must first copy the setup data into - // user memory, to allow for the 32-bit access that memcpy performs. - uint8_t userMemBuf[8]; + if ((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) { + /* Setup packet */ uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex); - /* Get SETUP Packet*/ - if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again. - { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) { // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) - pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); - pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); - dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); - dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); + pcd_set_ep_rx_status(USB, 0u, USB_EP_RX_NAK); + pcd_set_ep_tx_status(USB, 0u, USB_EP_TX_NAK); +#ifdef FSDEV_BUS_32BIT + dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); +#else + // The setup_received function uses memcpy, so this must first copy the setup data into + // user memory, to allow for the 32-bit access that memcpy performs. + uint8_t userMemBuf[8]; + dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB, EPindex), 8); + dcd_event_setup_received(0, (uint8_t *)userMemBuf, true); +#endif } - } - else - { + } else { + // Clear RX CTR interrupt flag + if (ep_addr != 0u) { + pcd_clear_rx_ep_ctr(USB, EPindex); + } + uint32_t count; + uint16_t addr; /* Read from correct register when ISOCHRONOUS (double buffered) */ - if ( (wEPRegVal & USB_EP_DTOG_RX) && ( (wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) ) { - count = pcd_get_ep_tx_cnt(USB, EPindex); + if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + if (wEPRegVal & USB_EP_DTOG_RX) { + count = pcd_get_ep_dbuf0_cnt(USB, EPindex); + addr = pcd_get_ep_dbuf0_address(USB, EPindex); + } else { + count = pcd_get_ep_dbuf1_cnt(USB, EPindex); + addr = pcd_get_ep_dbuf1_address(USB, EPindex); + } } else { count = pcd_get_ep_rx_cnt(USB, EPindex); + addr = pcd_get_ep_rx_address(USB, EPindex); } TU_ASSERT(count <= xfer->max_packet_size, /**/); - // Clear RX CTR interrupt flag - if(ep_addr != 0u) - { - pcd_clear_rx_ep_ctr(USB, EPindex); - } - - if (count != 0U) - { - uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex); - - if (xfer->ff) - { + if (count != 0U) { + if (xfer->ff) { dcd_read_packet_memory_ff(xfer->ff, addr, count); - } - else - { + } else { dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), addr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - /* RX COMPLETE */ + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // all bytes received or short packet dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Though the host could still send, we don't know. - // Does the bulk pipe need to be reset to valid to allow for a ZLP? - } - else - { - uint32_t remaining = (uint32_t)xfer->total_len - (uint32_t)xfer->queued_len; - if(remaining >= xfer->max_packet_size) { - pcd_set_ep_rx_bufsize(USB, EPindex,xfer->max_packet_size); - } else { - pcd_set_ep_rx_bufsize(USB, EPindex,remaining); - } - - if (!((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS)) { - /* Set endpoint active again for receiving more data. - * Note that isochronous endpoints stay active always */ - pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); + } else { + /* Set endpoint active again for receiving more data. + * Note that isochronous endpoints stay active always */ + if ((wEPRegVal & USB_EP_TYPE_MASK) != USB_EP_ISOCHRONOUS) { + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t cnt = tu_min16(remaining, xfer->max_packet_size); + pcd_set_ep_rx_cnt(USB, EPindex, cnt); } + pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); } } // For EP0, prepare to receive another SETUP packet. // Clear CTR last so that a new packet does not overwrite the packing being read. // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared) - if(ep_addr == 0u) - { - // Always be prepared for a status packet... - pcd_set_ep_rx_bufsize(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); + if (ep_addr == 0u) { + // Always be prepared for a status packet... + pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); pcd_clear_rx_ep_ctr(USB, EPindex); } } @@ -628,64 +640,60 @@ static void dcd_ep_ctr_handler(void) uint32_t wIstr; /* stay in loop while pending interrupts */ - while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) - { - - if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */ - { + while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) { + if ((wIstr & USB_ISTR_DIR) == 0U) { + /* TX/IN */ dcd_ep_ctr_tx_handler(wIstr); - } - else /* RX/OUT*/ - { + } else { + /* RX/OUT*/ dcd_ep_ctr_rx_handler(wIstr); } } } -void dcd_int_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) +{ - (void) rhport; + (void)rhport; uint32_t int_status = USB->ISTR; - //const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP - // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; - // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) + // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP + // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; + // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) // The ST driver loops here on the CTR bit, but that loop has been moved into the // dcd_ep_ctr_handler(), so less need to loop here. The other interrupts shouldn't // be triggered repeatedly. /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ - if(int_status & USB_ISTR_SOF) { - clear_istr_bits(USB_ISTR_SOF); + if (int_status & USB_ISTR_SOF) { + USB->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; dcd_event_sof(0, USB->FNR & USB_FNR_FN, true); } - if(int_status & USB_ISTR_RESET) { + if (int_status & USB_ISTR_RESET) { // USBRST is start of reset. - clear_istr_bits(USB_ISTR_RESET); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; dcd_handle_bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } - if (int_status & USB_ISTR_CTR) - { + if (int_status & USB_ISTR_CTR) { /* servicing of the endpoint correct transfer interrupt */ /* clear of the CTR flag into the sub */ dcd_ep_ctr_handler(); } - if (int_status & USB_ISTR_WKUP) - { - reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); - reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); - clear_istr_bits(USB_ISTR_WKUP); + if (int_status & USB_ISTR_WKUP) { + USB->CNTR &= ~USB_CNTR_LPMODE; + USB->CNTR &= ~USB_CNTR_FSUSP; + + USB->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - if (int_status & USB_ISTR_SUSP) - { + if (int_status & USB_ISTR_SUSP) { /* Suspend is asserted for both suspend and unplug events. without Vbus monitoring, * these events cannot be differentiated, so we only trigger suspend. */ @@ -694,20 +702,18 @@ void dcd_int_handler(uint8_t rhport) { USB->CNTR |= USB_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - clear_istr_bits(USB_ISTR_SUSP); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } - if(int_status & USB_ISTR_ESOF) { - if(remoteWakeCountdown == 1u) - { - USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); + if (int_status & USB_ISTR_ESOF) { + if (remoteWakeCountdown == 1u) { + USB->CNTR &= ~USB_CNTR_RESUME; } - if(remoteWakeCountdown > 0u) - { + if (remoteWakeCountdown > 0u) { remoteWakeCountdown--; } - clear_istr_bits(USB_ISTR_ESOF); + USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } } @@ -717,130 +723,73 @@ void dcd_int_handler(uint8_t rhport) { // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { - (void) rhport; + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; + request->bRequest == TUSB_REQ_SET_ADDRESS) { + uint8_t const dev_addr = (uint8_t)request->wValue; // Setting new address after the whole request is complete - reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); - USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set - } -} - -static void dcd_pma_alloc_reset(void) -{ - open_ep_count = 0; - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) - //TU_LOG2("dcd_pma_alloc_reset()\r\n"); - for(uint32_t i=0; ipma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_ptr = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_ptr = 0U; + USB->DADDR &= ~USB_DADDR_ADD; + USB->DADDR |= dev_addr; // leave the enable bit set } } /*** * Allocate a section of PMA - * - * If the EP number has already been allocated, and the new allocation - * is larger than the old allocation, then this will fail with a TU_ASSERT. - * (This is done to simplify the code. More complicated algorithms could be used) - * + * In case of double buffering, high 16bit is the address of 2nd buffer * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) +static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf) { - xfer_ctl_t* epXferCtl = xfer_ctl_ptr(ep_addr); - - if(epXferCtl->pma_alloc_size != 0U) - { - //TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr); - // Previously allocated - TU_ASSERT(length <= epXferCtl->pma_alloc_size, 0xFFFF); // Verify no larger than previous alloc - return epXferCtl->pma_ptr; - } - - open_ep_count++; + // Ensure allocated buffer is aligned +#ifdef FSDEV_BUS_32BIT + length = (length + 3) & ~0x03; +#else + length = (length + 1) & ~0x01; +#endif - uint16_t addr = ep_buf_ptr; + uint32_t addr = ep_buf_ptr; ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer - // Verify no overflow - TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF); + if (dbuf) { + addr |= ((uint32_t)ep_buf_ptr) << 16; + ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer + } - epXferCtl->pma_ptr = addr; - epXferCtl->pma_alloc_size = length; - //TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr); + // Verify packet buffer is not overflowed + TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF); return addr; } -/*** - * Free a block of PMA space - */ -static void dcd_pma_free(uint8_t ep_addr) -{ - // Presently, this should never be called for EP0 IN/OUT - TU_ASSERT(open_ep_count > 2, /**/); - TU_ASSERT(xfer_ctl_ptr(ep_addr)->max_packet_size != 0, /**/); - open_ep_count--; - - // If count is 2, only EP0 should be open, so allocations can be mostly reset. - - if(open_ep_count == 2) - { - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT + 2*CFG_TUD_ENDPOINT0_SIZE; // 8 bytes per endpoint (two TX and two RX words, each), and EP0 - - // Skip EP0 - for(uint32_t i=1; ipma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_alloc_size = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_OUT))->pma_ptr = 0U; - xfer_ctl_ptr(tu_edpt_addr(i,TUSB_DIR_IN))->pma_ptr = 0U; - } - } -} - /*** * Allocate hardware endpoint */ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) { uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - for(uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) - { + for (uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) { // Check if already allocated - if(ep_alloc_status[i].allocated[dir] && - ep_alloc_status[i].ep_type == ep_type && - ep_alloc_status[i].ep_num == epnum) - { + if (ep_alloc_status[i].allocated[dir] && + ep_alloc_status[i].ep_type == ep_type && + ep_alloc_status[i].ep_num == epnum) { return i; } // If EP of current direction is not allocated // Except for ISO endpoint, both direction should be free - if(!ep_alloc_status[i].allocated[dir] && - (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) - { + if (!ep_alloc_status[i].allocated[dir] && + (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) { // Check if EP number is the same - if(ep_alloc_status[i].ep_num == 0xFF || - ep_alloc_status[i].ep_num == epnum) - { + if (ep_alloc_status[i].ep_num == 0xFF || ep_alloc_status[i].ep_num == epnum) { // One EP pair has to be the same type - if(ep_alloc_status[i].ep_type == 0xFF || - ep_alloc_status[i].ep_type == ep_type) - { + if (ep_alloc_status[i].ep_type == 0xFF || ep_alloc_status[i].ep_type == ep_type) { ep_alloc_status[i].ep_num = epnum; ep_alloc_status[i].ep_type = ep_type; ep_alloc_status[i].allocated[dir] = true; @@ -855,121 +804,79 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) TU_ASSERT(0); } -/*** - * Free hardware endpoint - */ -static void dcd_ep_free(uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - for(uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) - { - // Check if EP number & dir are the same - if(ep_alloc_status[i].ep_num == epnum && - ep_alloc_status[i].allocated[dir] == dir) - { - ep_alloc_status[i].allocated[dir] = false; - // Reset entry if ISO endpoint or both direction are free - if(ep_alloc_status[i].ep_type == TUSB_XFER_ISOCHRONOUS || - !ep_alloc_status[i].allocated[dir ^ 1]) - { - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; - - return; - } - } - } -} - // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) { (void)rhport; - uint8_t const ep_idx = dcd_ep_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->bmAttributes.xfer); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; + uint8_t const ep_idx = dcd_ep_alloc(ep_addr, p_endpoint_desc->bmAttributes.xfer); + uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); uint16_t pma_addr; uint32_t wType; TU_ASSERT(ep_idx < STFSDEV_EP_COUNT); - TU_ASSERT(buffer_size <= 1024); + TU_ASSERT(buffer_size <= 64); // Set type - switch(p_endpoint_desc->bmAttributes.xfer) { - case TUSB_XFER_CONTROL: - wType = USB_EP_CONTROL; - break; - case TUSB_XFER_ISOCHRONOUS: - wType = USB_EP_ISOCHRONOUS; - break; - case TUSB_XFER_BULK: - wType = USB_EP_CONTROL; - break; - - case TUSB_XFER_INTERRUPT: - wType = USB_EP_INTERRUPT; - break; - - default: - TU_ASSERT(false); + switch (p_endpoint_desc->bmAttributes.xfer) { + case TUSB_XFER_CONTROL: + wType = USB_EP_CONTROL; + break; + case TUSB_XFER_BULK: + wType = USB_EP_CONTROL; + break; + + case TUSB_XFER_INTERRUPT: + wType = USB_EP_INTERRUPT; + break; + + default: + // Note: ISO endpoint should use alloc / active functions + TU_ASSERT(false); } pcd_set_eptype(USB, ep_idx, wType); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(p_endpoint_desc->bEndpointAddress)); - // Be normal, for now, instead of only accepting zero-byte packets (on control endpoint) - // or being double-buffered (bulk endpoints) - pcd_clear_ep_kind(USB,0); + pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - /* Create a packet memory buffer area. For isochronous endpoints, - * use the same buffer as the double buffer, essentially disabling double buffering */ - pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, buffer_size); + /* Create a packet memory buffer area. */ + pma_addr = dcd_pma_alloc(buffer_size, false); - if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) ) - { - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; - pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size); + if (dir == TUSB_DIR_IN) { + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); pcd_clear_tx_dtog(USB, ep_idx); - } - - if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) ) - { - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; - pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size); + } else { + pcd_set_ep_rx_address(USB, ep_idx, pma_addr); + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); pcd_clear_rx_dtog(USB, ep_idx); } - /* Enable endpoint */ - if (dir == TUSB_DIR_IN) - { - if(wType == USB_EP_ISOCHRONOUS) { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } else { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); - } - } else - { - if(wType == USB_EP_ISOCHRONOUS) { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - } else { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); - } - } - - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->max_packet_size = packet_size; - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->ep_idx = ep_idx; + xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; + xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; return true; } -void dcd_edpt_close_all (uint8_t rhport) +void dcd_edpt_close_all(uint8_t rhport) { - (void) rhport; - // TODO implement dcd_edpt_close_all() + (void)rhport; + + for (uint32_t i = 1; i < STFSDEV_EP_COUNT; i++) { + // Reset endpoint + pcd_set_endpoint(USB, i, 0); + // Clear EP allocation status + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].allocated[0] = false; + ep_alloc_status[i].allocated[1] = false; + } + + // Reset PMA allocation + ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * MAX_EP_COUNT + 2 * CFG_TUD_ENDPOINT0_SIZE; } /** @@ -979,223 +886,203 @@ void dcd_edpt_close_all (uint8_t rhport) * * This also clears transfers in progress, should there be any. */ -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if(dir == TUSB_DIR_IN) - { + if (dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } - else - { + } else { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); } - - dcd_ep_free(ep_addr); - - dcd_pma_free(ep_addr); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; - TU_ASSERT(largest_packet_size <= 1024); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); const uint16_t buffer_size = pcd_aligned_buffer_size(largest_packet_size); - /* Create a packet memory buffer area. For isochronous endpoints, - * use the same buffer as the double buffer, essentially disabling double buffering */ - uint16_t pma_addr = dcd_pma_alloc(ep_addr, buffer_size); - - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, + for smaller devices double buffering occupy too much space. */ +#if FSDEV_PMA_SIZE > 1024u + uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); + uint16_t pma_addr2 = pma_addr >> 16; +#else + uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); + uint16_t pma_addr2 = pma_addr; +#endif + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + pcd_set_ep_rx_address(USB, ep_idx, pma_addr2); pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; + xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; return true; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) { (void)rhport; - uint8_t const ep_idx = xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->ep_idx; - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; + uint8_t const ep_idx = xfer_ctl_ptr(ep_addr)->ep_idx; + uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); - const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); - /* Disable endpoint */ - if(dir == TUSB_DIR_IN) - { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } - else - { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - } + pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(p_endpoint_desc->bEndpointAddress)); - // Be normal, for now, instead of only accepting zero-byte packets (on control endpoint) - // or being double-buffered (bulk endpoints) - pcd_clear_ep_kind(USB,0); + pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size); - pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size); pcd_clear_tx_dtog(USB, ep_idx); pcd_clear_rx_dtog(USB, ep_idx); - xfer_ctl_ptr(p_endpoint_desc->bEndpointAddress)->max_packet_size = packet_size; + if (dir == TUSB_DIR_IN) { + pcd_rx_dtog(USB, ep_idx); + } else { + pcd_tx_dtog(USB, ep_idx); + } + + xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; return true; } // Currently, single-buffered, and only 64 bytes at a time (max) -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - - if(len > xfer->max_packet_size) // max packet size for FS transfer - { + if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix); - uint16_t addr_ptr = *pcd_ep_tx_address_ptr(USB,ep_ix); + bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + uint16_t addr_ptr; - if (xfer->ff) - { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); - } - else - { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + if (is_iso) { + if (ep_reg & USB_EP_DTOG_TX) { + addr_ptr = pcd_get_ep_dbuf1_address(USB, ep_ix); + pcd_set_ep_tx_dbuf1_cnt(USB, ep_ix, len); + } else { + addr_ptr = pcd_get_ep_dbuf0_address(USB, ep_ix); + pcd_set_ep_tx_dbuf0_cnt(USB, ep_ix, len); + } + } else { + addr_ptr = pcd_get_ep_tx_address(USB, ep_ix); + pcd_set_ep_tx_cnt(USB, ep_ix, len); } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - /* Write into correct register when ISOCHRONOUS (double buffered) */ - if ( (ep_reg & USB_EP_DTOG_TX) && ( (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) ) { - pcd_set_ep_rx_cnt(USB, ep_ix, len); + if (xfer->ff) { + dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); } else { - pcd_set_ep_tx_cnt(USB, ep_ix, len); + dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + dcd_int_disable(0); pcd_set_ep_tx_status(USB, ep_ix, USB_EP_TX_VALID); + if (is_iso) { + xfer->iso_in_sending = true; + } + dcd_int_enable(0); } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; + (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - - if ( dir == TUSB_DIR_OUT ) - { + if (dir == TUSB_DIR_IN) { + dcd_transmit_packet(xfer, ep_idx); + } else { // A setup token can occur immediately after an OUT STATUS packet so make sure we have a valid // buffer for the control endpoint. - if (ep_idx == 0 && buffer == NULL) - { - xfer->buffer = (uint8_t*)_setup_packet; + if (ep_idx == 0 && xfer->buffer == NULL) { + xfer->buffer = (uint8_t *)_setup_packet; } - if(total_bytes > xfer->max_packet_size) - { - pcd_set_ep_rx_bufsize(USB,ep_idx,xfer->max_packet_size); + uint32_t cnt = (uint32_t ) tu_min16(xfer->total_len, xfer->max_packet_size); + uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); + + if ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + pcd_set_ep_rx_dbuf0_cnt(USB, ep_idx, cnt); + pcd_set_ep_rx_dbuf1_cnt(USB, ep_idx, cnt); } else { - pcd_set_ep_rx_bufsize(USB,ep_idx,total_bytes); + pcd_set_ep_rx_cnt(USB, ep_idx, cnt); } + pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_VALID); } - else // IN - { - dcd_transmit_packet(xfer,ep_idx); - } + return true; } -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - (void) rhport; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); - uint8_t const epnum = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + return edpt_xfer(rhport, ep_addr); +} + +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) +{ + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); xfer->buffer = NULL; - xfer->ff = ff; + xfer->ff = ff; xfer->total_len = total_bytes; xfer->queued_len = 0; - if ( dir == TUSB_DIR_OUT ) - { - if(total_bytes > xfer->max_packet_size) - { - pcd_set_ep_rx_bufsize(USB,epnum,xfer->max_packet_size); - } else { - pcd_set_ep_rx_bufsize(USB,epnum,total_bytes); - } - pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID); - } - else // IN - { - dcd_transmit_packet(xfer,epnum); - } - return true; + return edpt_xfer(rhport, ep_addr); } -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) - { // IN + if (dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_STALL); - } - else - { // OUT + } else { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_STALL); } } -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) - { // IN - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { + if (dir == TUSB_DIR_IN) { // IN + if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); } /* Reset to DATA0 if clearing stall condition. */ pcd_clear_tx_dtog(USB, ep_idx); - } - else - { // OUT - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { + } else { // OUT + if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); } /* Reset to DATA0 if clearing stall condition. */ @@ -1203,89 +1090,144 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) } } +#ifdef FSDEV_BUS_32BIT +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) +{ + const uint8_t *srcVal = src; + volatile uint32_t *dst32 = (volatile uint32_t *)(USB_PMAADDR + dst); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + *dst32++ = tu_unaligned_read32(srcVal); + srcVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) { + uint32_t wrVal = *srcVal; + wNBytes--; + + if (wNBytes) { + wrVal |= *++srcVal << 8; + wNBytes--; + + if (wNBytes) { + wrVal |= *++srcVal << 16; + } + } + + *dst32 = wrVal; + } + + return true; +} +#else // Packet buffer access can only be 8- or 16-bit. /** - * @brief Copy a buffer from user memory area to packet memory area (PMA). - * This uses byte-access for user memory (so support non-aligned buffers) - * and 16-bit access for packet memory. - * @param dst, byte address in PMA; must be 16-bit aligned - * @param src pointer to user memory area. - * @param wPMABufAddr address into PMA. - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) + * @brief Copy a buffer from user memory area to packet memory area (PMA). + * This uses byte-access for user memory (so support non-aligned buffers) + * and 16-bit access for packet memory. + * @param dst, byte address in PMA; must be 16-bit aligned + * @param src pointer to user memory area. + * @param wPMABufAddr address into PMA. + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; uint16_t temp1, temp2; - const uint8_t * srcVal; + const uint8_t *srcVal; // The GCC optimizer will combine access to 32-bit sizes if we let it. Force // it volatile so that it won't do that. __IO uint16_t *pdwVal; srcVal = src; - pdwVal = &pma[PMA_STRIDE*(dst>>1)]; + pdwVal = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; - while (n--) - { + while (n--) { temp1 = (uint16_t)*srcVal; srcVal++; - temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)) ; + temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)); *pdwVal = temp2; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; srcVal++; } - if (wNBytes & 0x01) - { + if (wNBytes) { temp1 = *srcVal; *pdwVal = temp1; } return true; } +#endif /** - * @brief Copy from FIFO to packet memory area (PMA). - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes) + * @brief Copy from FIFO to packet memory area (PMA). + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); + uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (dst aligned to 16 bit) - if((cnt_lin & 0x01) && cnt_wrap) - { + // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit) +#ifdef FSDEV_BUS_32BIT + if ((cnt_lin & 0x03) && cnt_wrap) { // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin &~0x01); - dst += cnt_lin &~0x01; + dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x03); + dst += cnt_lin & ~0x03; + + // Copy last linear bytes & first wrapped bytes to buffer + uint32_t i; + uint8_t tmp[4]; + for (i = 0; i < (cnt_lin & 0x03); i++) { + tmp[i] = ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) { + tmp[i] = *(uint8_t *)info.ptr_wrap; + info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; + } + + // Write unaligned buffer + dcd_write_packet_memory(dst, &tmp, 4); + dst += 4; + + // Copy rest of wrapped byte + if (wCnt) + dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); + } +#else + if ((cnt_lin & 0x01) && cnt_wrap) { + // Copy first linear part + dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x01); + dst += cnt_lin & ~0x01; // Copy last linear byte & first wrapped byte - uint16_t tmp = ((uint8_t*)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t*)info.ptr_wrap)[0]) << 8U); + uint16_t tmp = ((uint8_t *)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t *)info.ptr_wrap)[0]) << 8U); dcd_write_packet_memory(dst, &tmp, 2); dst += 2; // Copy rest of wrapped byte - dcd_write_packet_memory(dst, ((uint8_t*)info.ptr_wrap) + 1, cnt_wrap - 1); + dcd_write_packet_memory(dst, ((uint8_t *)info.ptr_wrap) + 1, cnt_wrap - 1); } - else - { +#endif + else { // Copy linear part dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin); dst += info.len_lin; - if(info.len_wrap) - { + if (info.len_wrap) { // Copy wrapped byte dcd_write_packet_memory(dst, info.ptr_wrap, cnt_wrap); } @@ -1296,13 +1238,44 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN return true; } +#ifdef FSDEV_BUS_32BIT +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) +{ + uint8_t *dstVal = dst; + volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + tu_unaligned_write32(dstVal, *src32++); + dstVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) { + uint32_t rdVal = *src32; + + *dstVal = tu_u32_byte0(rdVal); + wNBytes--; + + if (wNBytes) { + *++dstVal = tu_u32_byte1(rdVal); + wNBytes--; + + if (wNBytes) { + *++dstVal = tu_u32_byte2(rdVal); + } + } + } + + return true; +} +#else /** - * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes) + * @brief Copy a buffer from packet memory area (PMA) to user memory area. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; // The GCC optimizer will combine access to 32-bit sizes if we let it. Force @@ -1310,70 +1283,93 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN __IO const uint16_t *pdwVal; uint32_t temp; - pdwVal = &pma[PMA_STRIDE*(src>>1)]; - uint8_t *dstVal = (uint8_t*)dst; + pdwVal = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; + uint8_t *dstVal = (uint8_t *)dst; - while (n--) - { + while (n--) { temp = *pdwVal; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; *dstVal++ = ((temp >> 0) & 0xFF); *dstVal++ = ((temp >> 8) & 0xFF); } - if (wNBytes & 0x01) - { + if (wNBytes & 0x01) { temp = *pdwVal; - pdwVal += PMA_STRIDE; + pdwVal += FSDEV_PMA_STRIDE; *dstVal++ = ((temp >> 0) & 0xFF); } return true; } +#endif /** - * @brief Copy a buffer from user packet memory area (PMA) to FIFO. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes) + * @brief Copy a buffer from user packet memory area (PMA) to FIFO. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO + tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); + uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); // We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (src aligned to 16 bit) - if((cnt_lin & 0x01) && cnt_wrap) - { + // To ensure PMA is always access aligned (src aligned to 16 or 32 bit) +#ifdef FSDEV_BUS_32BIT + if ((cnt_lin & 0x03) && cnt_wrap) { // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin &~0x01); - src += cnt_lin &~0x01; + dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x03); + src += cnt_lin & ~0x03; - // Copy last linear byte & first wrapped byte - uint16_t tmp; - dcd_read_packet_memory(&tmp, src, 2); + // Copy last linear bytes & first wrapped bytes + uint8_t tmp[4]; + dcd_read_packet_memory(tmp, src, 4); + src += 4; + + uint32_t i; + for (i = 0; i < (cnt_lin & 0x03); i++) { + ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i] = tmp[i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) { + *(uint8_t *)info.ptr_wrap = tmp[i]; + info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; + } - ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = (uint8_t)tmp; - ((uint8_t*)info.ptr_wrap)[0] = (uint8_t)(tmp >> 8U); + // Copy rest of wrapped byte + if (wCnt) + dcd_read_packet_memory(info.ptr_wrap, src, wCnt); + } +#else + if ((cnt_lin & 0x01) && cnt_wrap) { + // Copy first linear part + dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x01); + src += cnt_lin & ~0x01; + + // Copy last linear byte & first wrapped byte + uint8_t tmp[2]; + dcd_read_packet_memory(tmp, src, 2); src += 2; + ((uint8_t *)info.ptr_lin)[cnt_lin - 1] = tmp[0]; + ((uint8_t *)info.ptr_wrap)[0] = tmp[1]; + // Copy rest of wrapped byte - dcd_read_packet_memory(((uint8_t*)info.ptr_wrap) + 1, src, cnt_wrap - 1); + dcd_read_packet_memory(((uint8_t *)info.ptr_wrap) + 1, src, cnt_wrap - 1); } - else - { +#endif + else { // Copy linear part dcd_read_packet_memory(info.ptr_lin, src, cnt_lin); src += cnt_lin; - if(info.len_wrap) - { + if (info.len_wrap) { // Copy wrapped byte dcd_read_packet_memory(info.ptr_wrap, src, cnt_wrap); } diff --git a/test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h similarity index 53% rename from test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h index e3fc8aeb..7992f34a 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/st/stm32_fsdev/dcd_stm32_fsdev.h @@ -1,34 +1,36 @@ -/** - * Copyright(c) 2016 STMicroelectronics - * Copyright(c) N Conrad - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ +/* + * Copyright(c) 2016 STMicroelectronics + * Copyright(c) N Conrad + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the TinyUSB stack. + */ // This file contains source copied from ST's HAL, and thus should have their copyright statement. -// PMA_LENGTH is PMA buffer size in bytes. +// FSDEV_PMA_SIZE is PMA buffer size in bytes. // On 512-byte devices, access with a stride of two words (use every other 16-bit address) // On 1024-byte devices, access with a stride of one word (use every 16-bit address) @@ -37,7 +39,7 @@ #if CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) // F0x2 models are crystal-less // All have internal D+ pull-up // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support @@ -45,7 +47,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word @@ -56,7 +58,7 @@ defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) #include "stm32f3xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) @@ -65,37 +67,98 @@ defined(STM32F302xD) || defined(STM32F302xE) || \ defined(STM32F303xD) || defined(STM32F303xE) #include "stm32f3xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support // When CAN clock is enabled, USB can use first 768 bytes ONLY. #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 #include "stm32l1xx.h" - #define PMA_LENGTH (512u) + #define FSDEV_PMA_SIZE (512u) #elif CFG_TUSB_MCU == OPT_MCU_STM32G4 #include "stm32g4xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + #include "stm32h5xx.h" + #define FSDEV_BUS_32BIT + + #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) + #define USB_DRD_BASE USB_DRD_FS_BASE + #endif + + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) /* ST provided header has incorrect value */ #undef USB_PMAADDR #define USB_PMAADDR USB1_PMAADDR #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 #include "stm32l5xx.h" - #define PMA_LENGTH (1024u) + #define FSDEV_PMA_SIZE (1024u) #ifndef USB_PMAADDR #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) @@ -107,25 +170,41 @@ #endif // For purposes of accessing the packet -#if ((PMA_LENGTH) == 512u) - #define PMA_STRIDE (2u) -#elif ((PMA_LENGTH) == 1024u) - #define PMA_STRIDE (1u) +#if ((FSDEV_PMA_SIZE) == 512u) + #define FSDEV_PMA_STRIDE (2u) +#elif ((FSDEV_PMA_SIZE) == 1024u) + #define FSDEV_PMA_STRIDE (1u) #endif -// And for type-safety create a new macro for the volatile address of PMAADDR +// The fsdev_bus_t type can be used for both register and PMA access necessities +// For type-safety create a new macro for the volatile address of PMAADDR // The compiler should warn us if we cast it to a non-volatile type? +#ifdef FSDEV_BUS_32BIT +typedef uint32_t fsdev_bus_t; +static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; + +#else +typedef uint16_t fsdev_bus_t; // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; -// prototypes -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue); +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { + size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; + total_word_offset *= FSDEV_PMA_STRIDE; + return &(pma[total_word_offset]); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +} +#endif /* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) { /* The STM32 full speed USB peripheral supports only a limited set of * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ uint16_t blocksize = (size > 62) ? 32 : 2; @@ -136,21 +215,28 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si return numblocks * blocksize; } -/* SetENDPOINT */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); + *reg = wRegValue; +#else __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u); *reg = (uint16_t)wRegValue; +#endif } -/* GetENDPOINT */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); +#else __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u); +#endif return *reg; } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= (uint32_t)USB_EP_T_MASK; regVal |= wType; @@ -158,20 +244,19 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EP_T_FIELD; return regVal; } + /** * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. * @param USBx USB peripheral instance register address. * @param bEpIdx Endpoint Number. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal &= ~USB_EP_CTR_RX; @@ -179,51 +264,42 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal &= ~USB_EP_CTR_TX; regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) pcd_set_endpoint(USBx, bEpIdx,regVal); } + /** * @brief gets counter of the tx buffer. * @param USBx USB peripheral instance register address. * @param bEpIdx Endpoint Number. * @retval Counter value */ -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; +#else __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; +#endif } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; +#else __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; +#endif } -/** - * @brief Sets counter of rx buffer with no. of blocks. - * @param dwReg Register - * @param wCount Counter. - * @param wNBlocks no. of Blocks. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwReg, size_t wCount) -{ - /* We assume that the buffer size is already aligned to hardware requirements. */ - uint16_t blocksize = (wCount > 62) ? 1 : 0; - uint16_t numblocks = wCount / (blocksize ? 32 : 2); - - /* There should be no remainder in the above calculation */ - TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); -} +#define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt +#define pcd_get_ep_dbuf1_cnt pcd_get_ep_rx_cnt /** * @brief Sets address in an endpoint register. @@ -232,8 +308,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwRe * @param bAddr Address. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= bAddr; @@ -241,59 +316,106 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) -{ - size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; - total_word_offset *= PMA_STRIDE; - return &(pma[total_word_offset]); +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx] & 0x0000FFFFu ; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); +#endif } -// Pointers to the PMA table entries (using the ARM address space) -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); -} -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx + 1] & 0x0000FFFFu; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#endif } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#define pcd_get_ep_dbuf0_address pcd_get_ep_tx_address +#define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; +#endif } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) -{ - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ +#define pcd_set_ep_dbuf0_address pcd_set_ep_tx_address +#define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ +#define pcd_set_ep_tx_dbuf0_cnt pcd_set_ep_tx_cnt + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else __IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ - __IO uint16_t *pdwReg = pcd_ep_tx_cnt_ptr((USBx),(bEpIdx)); - wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, wCount); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, + uint32_t blocksize, uint32_t numblocks) { + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); +#else + __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); + *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); +#endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) -{ - __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpIdx)); +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, wCount); + + /* We assume that the buffer size is already aligned to hardware requirements. */ + uint16_t blocksize = (wCount > 62) ? 1 : 0; + uint16_t numblocks = wCount / (blocksize ? 32 : 2); + + /* There should be no remainder in the above calculation */ + TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_dbuf0_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount); } +#define pcd_set_ep_rx_dbuf1_cnt pcd_set_ep_rx_cnt + /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. @@ -301,8 +423,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USB * @param wState new state * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPTX_DTOGMASK; @@ -319,7 +440,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); -} /* pcd_set_ep_tx_status */ +} /** * @brief sets the status for rx transfer (bits STAT_TX[1:0]) @@ -329,31 +450,27 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPRX_DTOGMASK; /* toggle first bit ? */ - if((USB_EPRX_DTOG1 & wState)!= 0U) - { + if((USB_EPRX_DTOG1 & wState)!= 0U) { regVal ^= USB_EPRX_DTOG1; } /* toggle second bit ? */ - if((USB_EPRX_DTOG2 & wState)!= 0U) - { + if((USB_EPRX_DTOG2 & wState)!= 0U) { regVal ^= USB_EPRX_DTOG2; } regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); -} /* pcd_set_ep_rx_status */ +} -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); return (regVal & USB_EPRX_STAT) >> (12u); -} /* pcd_get_ep_rx_status */ +} /** @@ -362,16 +479,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * * @param bEpIdx Endpoint Number. * @retval None */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; @@ -384,21 +499,16 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32 * @param bEpIdx Endpoint Number. * @retval None */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_RX) != 0) - { + if((regVal & USB_EP_DTOG_RX) != 0) { pcd_rx_dtog(USBx,bEpIdx); } } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_TX) != 0) - { + if((regVal & USB_EP_DTOG_TX) != 0) { pcd_tx_dtog(USBx,bEpIdx); } } @@ -409,17 +519,15 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, * @param bEpIdx Endpoint Number. * @retval None */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) -{ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal |= USB_EP_KIND; regVal &= USB_EPREG_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) -{ + +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPKIND_MASK; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dcd_dwc2.c b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c similarity index 60% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dcd_dwc2.c rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c index aa6757ee..692096fc 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dcd_dwc2.c +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dcd_dwc2.c @@ -82,8 +82,8 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { - uint8_t * buffer; - tu_fifo_t * ff; + uint8_t* buffer; + tu_fifo_t* ff; uint16_t total_len; uint16_t max_size; uint8_t interval; @@ -93,45 +93,182 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) // EP0 transfers are limited to 1 packet - larger sizes has to be split -static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type // TX FIFO RAM allocation so far in words - RX FIFO size is readily available from dwc2->grxfsiz -static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) -static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) +static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by static bool _sof_en; -// Calculate the RX FIFO size according to recommendations from reference manual -static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count) -{ - return 15 + 2*(max_ep_size/4) + 2*ep_count; +// Calculate the RX FIFO size according to minimum recommendations from reference manual +// RxFIFO = (5 * number of control endpoints + 8) + +// ((largest USB packet used / 4) + 1 for status information) + +// (2 * number of OUT endpoints) + 1 for Global NAK +// with number of control endpoints = 1 we have +// RxFIFO = 15 + (largest USB packet used / 4) + 2 * number of OUT endpoints +// we double the largest USB packet size to be able to hold up to 2 packets +static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count) { + return 15 + 2 * (max_ep_size / 4) + 2 * ep_count; } -static void update_grxfsiz(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +TU_ATTR_ALWAYS_INLINE static inline void fifo_flush_tx(dwc2_regs_t* dwc2, uint8_t epnum) { + // flush TX fifo and wait for it cleared + dwc2->grstctl = GRSTCTL_TXFFLSH | (epnum << GRSTCTL_TXFNUM_Pos); + while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {} +} +TU_ATTR_ALWAYS_INLINE static inline void fifo_flush_rx(dwc2_regs_t* dwc2) { + // flush RX fifo and wait for it cleared + dwc2->grstctl = GRSTCTL_RXFFLSH; + while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {} +} + +static bool fifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_ASSERT(epnum < ep_count); + + uint16_t fifo_size = tu_div_ceil(packet_size, 4); + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z + // | IN FIFO MAX | + // --------------- + // | FREE | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // In FIFO is allocated by following rules: + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + if (dir == TUSB_DIR_OUT) { + // Calculate required size of RX FIFO + uint16_t const sz = calc_grxfsiz(4 * fifo_size, ep_count); + + // If size_rx needs to be extended check if possible and if so enlarge it + if (dwc2->grxfsiz < sz) { + TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size / 4); + + // Enlarge RX FIFO + dwc2->grxfsiz = sz; + } + } else { + // Note if The TXFELVL is configured as half empty. In order + // to be able to write a packet at that point, the fifo must be twice the max_size. + if ((dwc2->gahbcfg & GAHBCFG_TXFELVL) == 0) { + fifo_size *= 2; + } - // Determine largest EP size for RX FIFO - uint16_t max_epsize = 0; - for (uint8_t epnum = 0; epnum < ep_count; epnum++) - { - max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size); + // Check if free space is available + TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size / 4); + _allocated_fifo_words_tx += fifo_size; + TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %" PRIu32, fifo_size * 4, + _dwc2_controller[rhport].ep_fifo_size - _allocated_fifo_words_tx * 4); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | + (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx); } - // Update size of RX FIFO - dwc2->grxfsiz = calc_grxfsiz(max_epsize, ep_count); + return true; +} + +static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); + xfer->interval = p_endpoint_desc->bInterval; + + // USBAEP, EPTYP, SD0PID_SEVNFRM, MPSIZ are the same for IN and OUT endpoints. + uint32_t const dxepctl = (1 << DOEPCTL_USBAEP_Pos) | + (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | + (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DOEPCTL_MPSIZ_Pos); + + if (dir == TUSB_DIR_OUT) { + dwc2->epout[epnum].doepctl = dxepctl; + dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); + } else { + dwc2->epin[epnum].diepctl = dxepctl | (epnum << DIEPCTL_TXFNUM_Pos); + dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum)); + } +} + +static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { + (void) rhport; + + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + dwc2_epin_t* epin = dwc2->epin; + + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA)) { + epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + } else { + // Stop transmitting packets and NAK IN xfers. + epin[epnum].diepctl |= DIEPCTL_SNAK; + while ((epin[epnum].diepint & DIEPINT_INEPNE) == 0) {} + + // Disable the endpoint. + epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + while ((epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0) {} + + epin[epnum].diepint = DIEPINT_EPDISD; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + fifo_flush_tx(dwc2, epnum); + } else { + dwc2_epout_t* epout = dwc2->epout; + + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA)) { + epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + dwc2->dctl |= DCTL_SGONAK; + while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} + + // Ditto here- disable the endpoint. + epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + while ((epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0) {} + + epout[epnum].doepint = DOEPINT_EPDISD; + + // Allow other OUT endpoints to keep receiving. + dwc2->dctl |= DCTL_CGONAK; + } + } } // Start of Bus Reset -static void bus_reset(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void bus_reset(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; tu_memclr(xfer_status, sizeof(xfer_status)); - _out_ep_closed = false; _sof_en = false; @@ -139,15 +276,24 @@ static void bus_reset(uint8_t rhport) dwc2->dcfg &= ~DCFG_DAD_Msk; // 1. NAK for all OUT endpoints - for ( uint8_t n = 0; n < ep_count; n++ ) - { + for (uint8_t n = 0; n < ep_count; n++) { dwc2->epout[n].doepctl |= DOEPCTL_SNAK; } - // 2. Set up interrupt mask + // 2. Disable all IN endpoints + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { + dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + } + } + + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); + + // 3. Set up interrupt mask dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); - dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; - dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; + dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; + dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture @@ -206,38 +352,34 @@ static void bus_reset(uint8_t rhport) _allocated_fifo_words_tx = 16; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx); + dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx); // Fixed control EP0 size to 64 bytes dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN ].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; } -static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) -{ +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, + uint16_t total_bytes) { (void) rhport; - TU_ASSERT(epnum < DWC2_EP_MAX, ); - - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // EP0 is limited to one packet each xfer // We use multiple transaction of xfer->max_size length to get a whole transfer done - if ( epnum == 0 ) - { - xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, dir); + if (epnum == 0) { + xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir); total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); ep0_pending[dir] -= total_bytes; } // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - if ( dir == TUSB_DIR_IN ) - { + if (dir == TUSB_DIR_IN) { dwc2_epin_t* epin = dwc2->epin; // A full IN transfer (multiple packets, possibly) triggers XFRC. @@ -247,20 +389,16 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; // For ISO endpoint set correct odd/even bit for next frame. - if ( (epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1 ) - { + if ((epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); } // Enable fifo empty interrupt only if there are something to put in the fifo. - if ( total_bytes != 0 ) - { + if (total_bytes != 0) { dwc2->diepempmsk |= (1 << epnum); } - } - else - { + } else { dwc2_epout_t* epout = dwc2->epout; // A full OUT transfer (multiple packets, possibly) triggers XFRC. @@ -269,9 +407,8 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c ((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk); epout[epnum].doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; - if ( (epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && - XFER_CTL_BASE(epnum, dir)->interval == 1 ) - { + if ((epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && + XFER_CTL_BASE(epnum, dir)->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); epout[epnum].doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); @@ -283,103 +420,46 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c /* Controller API *------------------------------------------------------------------*/ #if CFG_TUSB_DEBUG >= DWC2_DEBUG -void print_dwc2_info(dwc2_regs_t * dwc2) -{ - dwc2_ghwcfg2_t const * hw_cfg2 = &dwc2->ghwcfg2_bm; - dwc2_ghwcfg3_t const * hw_cfg3 = &dwc2->ghwcfg3_bm; - dwc2_ghwcfg4_t const * hw_cfg4 = &dwc2->ghwcfg4_bm; - -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); - TU_LOG_HEX(DWC2_DEBUG, dwc2->guid); - TU_LOG_HEX(DWC2_DEBUG, dwc2->gsnpsid); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg1); - - // HW configure 2 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg2); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->op_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->arch ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->point2point ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->hs_phy_type ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->fs_phy_type ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_dev_ep ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_host_ch ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->period_channel_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->enable_dynamic_fifo ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->mul_cpu_int ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->nperiod_tx_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->host_period_tx_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->dev_token_q_depth ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg2->otg_enable_ic_usb ); - - // HW configure 3 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg3); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->xfer_size_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->packet_size_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->i2c_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->vendor_ctrl_itf ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->optional_feature_removed ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->synch_reset ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_adp_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable_hsic ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->battery_charger_support ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->lpm_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg3->total_fifo_size ); - - // HW configure 4 - TU_LOG(DWC2_DEBUG, "\r\n"); - TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg4); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_period_in_ep ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->power_optimized ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ahb_freq_min ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->hibernation ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->service_interval_mode ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ipg_isoc_en ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->acg_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->utmi_phy_data_width ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dev_ctrl_ep_num ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->iddg_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->vbus_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->a_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->b_valid_filter_enabled ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dedicated_fifos ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_in_eps ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_desc_enable ); - TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_dynamic ); +void print_dwc2_info(dwc2_regs_t* dwc2) { + // print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 + // use dwc2_info.py/md for bit-field value and comparison with other ports + volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid; + TU_LOG(DWC2_DEBUG, "guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n"); + for (size_t i = 0; i < 5; i++) { + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 ", ", p[i]); + } + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 "\r\n", p[5]); } #endif -static void reset_core(dwc2_regs_t * dwc2) -{ +static void reset_core(dwc2_regs_t* dwc2) { // reset core dwc2->grstctl |= GRSTCTL_CSRST; // wait for reset bit is cleared // TODO version 4.20a should wait for RESET DONE mask - while (dwc2->grstctl & GRSTCTL_CSRST) { } + while (dwc2->grstctl & GRSTCTL_CSRST) {} // wait for AHB master IDLE - while ( !(dwc2->grstctl & GRSTCTL_AHBIDL) ) { } + while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for device mode ? } -static bool phy_hs_supported(dwc2_regs_t * dwc2) -{ - // note: esp32 incorrect report its hs_phy_type as utmi +static bool phy_hs_supported(dwc2_regs_t* dwc2) { + (void) dwc2; + #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // note: esp32 incorrect report its hs_phy_type as utmi + return false; +#elif !TUD_OPT_HIGH_SPEED return false; #else - return TUD_OPT_HIGH_SPEED && dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE; + return dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE; #endif } -static void phy_fs_init(dwc2_regs_t * dwc2) -{ +static void phy_fs_init(dwc2_regs_t* dwc2) { TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n"); // Select FS PHY @@ -403,15 +483,13 @@ static void phy_fs_init(dwc2_regs_t * dwc2) dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos); } -static void phy_hs_init(dwc2_regs_t * dwc2) -{ +static void phy_hs_init(dwc2_regs_t* dwc2) { uint32_t gusbcfg = dwc2->gusbcfg; // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; - if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) - { + if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) { TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n"); // Select ULPI @@ -425,8 +503,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2) // Disable FS/LS ULPI gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM); - }else - { + } else { TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n"); // Select UTMI+ with 8-bit interface @@ -467,8 +544,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2) dwc2->dcfg = dcfg; } -static bool check_dwc2(dwc2_regs_t * dwc2) -{ +static bool check_dwc2(dwc2_regs_t* dwc2) { #if CFG_TUSB_DEBUG >= DWC2_DEBUG print_dwc2_info(dwc2); #endif @@ -483,41 +559,35 @@ static bool check_dwc2(dwc2_regs_t * dwc2) return true; } -void dcd_init (uint8_t rhport) -{ +void dcd_init(uint8_t rhport) { // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Check Synopsys ID register, failed if controller clock/power is not enabled - TU_VERIFY(check_dwc2(dwc2), ); - + if (!check_dwc2(dwc2)) return; dcd_disconnect(rhport); // max number of endpoints & total_fifo_size are: // hw_cfg2->num_dev_ep, hw_cfg2->total_fifo_size - if( phy_hs_supported(dwc2) ) - { - // Highspeed - phy_hs_init(dwc2); - }else - { - // core does not support highspeed or hs-phy is not present - phy_fs_init(dwc2); + if (phy_hs_supported(dwc2)) { + phy_hs_init(dwc2); // Highspeed + } else { + phy_fs_init(dwc2); // core does not support highspeed or hs phy is not present } // Restart PHY clock dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); - /* Set HS/FS Timeout Calibration to 7 (max available value). - * The number of PHY clocks that the application programs in - * this field is added to the high/full speed interpacket timeout - * duration in the core to account for any additional delays - * introduced by the PHY. This can be required, because the delay - * introduced by the PHY in generating the linestate condition - * can vary from one PHY to another. - */ + /* Set HS/FS Timeout Calibration to 7 (max available value). + * The number of PHY clocks that the application programs in + * this field is added to the high/full speed interpacket timeout + * duration in the core to account for any additional delays + * introduced by the PHY. This can be required, because the delay + * introduced by the PHY in generating the linestate condition + * can vary from one PHY to another. + */ dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); // Force device mode @@ -530,6 +600,9 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. dwc2->dcfg |= DCFG_NZLSOHSK; + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); + // Clear all interrupts uint32_t int_mask = dwc2->gintsts; dwc2->gintsts |= int_mask; @@ -537,11 +610,12 @@ void dcd_init (uint8_t rhport) dwc2->gotgint |= int_mask; // Required as part of core initialization. - // TODO: How should mode mismatch be handled? It will cause - // the core to stop working/require reset. - dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_MMISM | GINTMSK_RXFLVLM | + dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_RXFLVLM | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; + // Configure TX FIFO empty level for interrupt. Default is complete empty + dwc2->gahbcfg |= GAHBCFG_TXFELVL; + // Enable global interrupt dwc2->gahbcfg |= GAHBCFG_GINT; @@ -556,30 +630,26 @@ void dcd_init (uint8_t rhport) dcd_connect(rhport); } -void dcd_int_enable (uint8_t rhport) -{ +void dcd_int_enable(uint8_t rhport) { dwc2_dcd_int_enable(rhport); } -void dcd_int_disable (uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { dwc2_dcd_int_disable(rhport); } -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); // Response with status after changing device address dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_remote_wakeup(uint8_t rhport) -{ +void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); // set remote wakeup dwc2->dctl |= DCTL_RWUSIG; @@ -594,35 +664,29 @@ void dcd_remote_wakeup(uint8_t rhport) dwc2->dctl &= ~DCTL_RWUSIG; } -void dcd_connect(uint8_t rhport) -{ +void dcd_connect(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dctl &= ~DCTL_SDIS; } -void dcd_disconnect(uint8_t rhport) -{ +void dcd_disconnect(uint8_t rhport) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2->dctl |= DCTL_SDIS; } // Be advised: audio, video and possibly other iso-ep classes use dcd_sof_enable() to enable/disable its corresponding ISR on purpose! -void dcd_sof_enable(uint8_t rhport, bool en) -{ +void dcd_sof_enable(uint8_t rhport, bool en) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); _sof_en = en; - if (en) - { + if (en) { dwc2->gintsts = GINTSTS_SOF; dwc2->gintmsk |= GINTMSK_SOFM; - } - else - { + } else { dwc2->gintmsk &= ~GINTMSK_SOFM; } } @@ -631,143 +695,78 @@ void dcd_sof_enable(uint8_t rhport, bool en) /* DCD Endpoint port *------------------------------------------------------------------*/ -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) -{ - (void) rhport; - - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < ep_count); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - xfer->interval = desc_edpt->bInterval; - - uint16_t const fifo_size = tu_div_ceil(xfer->max_size, 4); - - if(dir == TUSB_DIR_OUT) - { - // Calculate required size of RX FIFO - uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count); - - // If size_rx needs to be extended check if possible and if so enlarge it - if (dwc2->grxfsiz < sz) - { - TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4); - - // Enlarge RX FIFO - dwc2->grxfsiz = sz; - } - - dwc2->epout[epnum].doepctl |= (1 << DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DOEPCTL_MPSIZ_Pos); - - dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); - } - else - { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO 0 | - // --------------- (320 or 1024) - 16 - // | IN FIFO 1 | - // --------------- (320 or 1024) - 16 - x - // | . . . . | - // --------------- (320 or 1024) - 16 - x - y - ... - z - // | IN FIFO MAX | - // --------------- - // | FREE | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // In FIFO is allocated by following rules: - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - // Check if free space is available - TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size/4); - - _allocated_fifo_words_tx += fifo_size; - - TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size*4, _dwc2_controller[rhport].ep_fifo_size-_allocated_fifo_words_tx*4); - - // DIEPTXF starts at FIFO #1. - // Both TXFD and TXSA are in unit of 32-bit words. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx); - - dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) | - (epnum << DIEPCTL_TXFNUM_Pos) | - (desc_edpt->bmAttributes.xfer << DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DIEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DIEPCTL_MPSIZ_Pos); - - dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum)); - } - +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { + TU_ASSERT(fifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt))); + edpt_activate(rhport, desc_edpt); return true; } // Close all non-control endpoints, cancel all pending transfers if any. -void dcd_edpt_close_all (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +void dcd_edpt_close_all(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; // Disable non-control interrupt dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); - for(uint8_t n = 1; n < ep_count; n++) - { + for (uint8_t n = 1; n < ep_count; n++) { // disable OUT endpoint - dwc2->epout[n].doepctl = 0; + if (dwc2->epout[n].doepctl & DOEPCTL_EPENA) { + dwc2->epout[n].doepctl |= DOEPCTL_SNAK | DOEPCTL_EPDIS; + } xfer_status[n][TUSB_DIR_OUT].max_size = 0; // disable IN endpoint - dwc2->epin[n].diepctl = 0; + if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { + dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + } xfer_status[n][TUSB_DIR_IN].max_size = 0; } + // reset allocated fifo OUT + dwc2->grxfsiz = calc_grxfsiz(64, ep_count); // reset allocated fifo IN _allocated_fifo_words_tx = 16; + + fifo_flush_tx(dwc2, 0x10); // all tx fifo + fifo_flush_rx(dwc2); } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + TU_ASSERT(fifo_alloc(rhport, ep_addr, largest_packet_size)); + return true; +} - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - TU_ASSERT(epnum < ep_count); +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + // Disable EP to clear potential incomplete transfers + edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + edpt_activate(rhport, p_endpoint_desc); + + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; // EP0 can only handle one packet - if(epnum == 0) - { + if (epnum == 0) { ep0_pending[dir] = total_bytes; // Schedule the first transaction for EP0 transfer edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); - } - else - { + } else { uint16_t num_packets = (total_bytes / xfer->max_size); uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if ( (short_packet_size > 0) || (total_bytes == 0) ) num_packets++; + if ((short_packet_size > 0) || (total_bytes == 0)) num_packets++; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -780,27 +779,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - TU_ASSERT(epnum < ep_count); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; uint16_t num_packets = (total_bytes / xfer->max_size); uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if ( short_packet_size > 0 || (total_bytes == 0) ) num_packets++; + if (short_packet_size > 0 || (total_bytes == 0)) num_packets++; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -808,123 +803,27 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } -static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) -{ - (void) rhport; - - dwc2_regs_t *dwc2 = DWC2_REG(rhport); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if ( dir == TUSB_DIR_IN ) - { - dwc2_epin_t* epin = dwc2->epin; - - // Only disable currently enabled non-control endpoint - if ( (epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA) ) - { - epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); - } - else - { - // Stop transmitting packets and NAK IN xfers. - epin[epnum].diepctl |= DIEPCTL_SNAK; - while ( (epin[epnum].diepint & DIEPINT_INEPNE) == 0 ) {} - - // Disable the endpoint. - epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); - while ( (epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0 ) {} - - epin[epnum].diepint = DIEPINT_EPDISD; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - dwc2->grstctl = ((epnum << GRSTCTL_TXFNUM_Pos) | GRSTCTL_TXFFLSH); - while ( (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) != 0 ) {} - } - else - { - dwc2_epout_t* epout = dwc2->epout; - - // Only disable currently enabled non-control endpoint - if ( (epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA) ) - { - epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; - } - else - { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - dwc2->dctl |= DCTL_SGONAK; - while ( (dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0 ) {} - - // Ditto here- disable the endpoint. - epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); - while ( (epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0 ) {} - - epout[epnum].doepint = DOEPINT_EPDISD; - - // Allow other OUT endpoints to keep receiving. - dwc2->dctl |= DCTL_CGONAK; - } - } -} - -/** - * Close an endpoint. - */ -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_disable(rhport, ep_addr, false); - - // Update max_size - xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation - - if (dir == TUSB_DIR_IN) - { - uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos; - uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos; - - // For now only the last opened endpoint can be closed without fuss. - TU_ASSERT(fifo_start == _dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx,); - _allocated_fifo_words_tx -= fifo_size; - } - else - { - _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty - } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + edpt_disable(rhport, ep_addr, false); } -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - dcd_edpt_disable(rhport, ep_addr, true); +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + edpt_disable(rhport, ep_addr, true); } -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // Clear stall and reset data toggle - if ( dir == TUSB_DIR_IN ) - { + if (dir == TUSB_DIR_IN) { dwc2->epin[epnum].diepctl &= ~DIEPCTL_STALL; dwc2->epin[epnum].diepctl |= DIEPCTL_SD0PID_SEVNFRM; - } - else - { + } else { dwc2->epout[epnum].doepctl &= ~DOEPCTL_STALL; dwc2->epout[epnum].doepctl |= DOEPCTL_SD0PID_SEVNFRM; } @@ -933,70 +832,63 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ // Read a single data packet from receive FIFO -static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len) -{ +static void read_fifo_packet(uint8_t rhport, uint8_t* dst, uint16_t len) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile const uint32_t * rx_fifo = dwc2->fifo[0]; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile const uint32_t* rx_fifo = dwc2->fifo[0]; // Reading full available 32 bit words from fifo uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { tu_unaligned_write32(dst, *rx_fifo); dst += 4; } // Read the remaining 1-3 bytes from fifo uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem != 0 ) - { + if (bytes_rem != 0) { uint32_t const tmp = *rx_fifo; dst[0] = tu_u32_byte0(tmp); - if ( bytes_rem > 1 ) dst[1] = tu_u32_byte1(tmp); - if ( bytes_rem > 2 ) dst[2] = tu_u32_byte2(tmp); + if (bytes_rem > 1) dst[1] = tu_u32_byte1(tmp); + if (bytes_rem > 2) dst[2] = tu_u32_byte2(tmp); } } // Write a single data packet to EPIN FIFO -static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const * src, uint16_t len) -{ +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* src, uint16_t len) { (void) rhport; - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile uint32_t * tx_fifo = dwc2->fifo[fifo_num]; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num]; // Pushing full available 32 bit words to fifo uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { *tx_fifo = tu_unaligned_read32(src); src += 4; } // Write the remaining 1-3 bytes into fifo uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + if (bytes_rem) { uint32_t tmp_word = src[0]; - if ( bytes_rem > 1 ) tmp_word |= (src[1] << 8); - if ( bytes_rem > 2 ) tmp_word |= (src[2] << 16); + if (bytes_rem > 1) tmp_word |= (src[1] << 8); + if (bytes_rem > 2) tmp_word |= (src[2] << 16); *tx_fifo = tmp_word; } } -static void handle_rxflvl_irq(uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); - volatile uint32_t const * rx_fifo = dwc2->fifo[0]; +static void handle_rxflvl_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + volatile uint32_t const* rx_fifo = dwc2->fifo[0]; // Pop control word off FIFO uint32_t const ctl_word = dwc2->grxstsp; - uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk ) >> GRXSTSP_PKTSTS_Pos; - uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk ) >> GRXSTSP_EPNUM_Pos; - uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk ) >> GRXSTSP_BCNT_Pos; + uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; + uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; + uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; dwc2_epout_t* epout = &dwc2->epout[epnum]; @@ -1011,10 +903,10 @@ static void handle_rxflvl_irq(uint8_t rhport) // TU_LOG(DWC2_DEBUG, " daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint); //#endif - switch ( pktsts ) - { + switch (pktsts) { // Global OUT NAK: do nothing - case GRXSTS_PKTSTS_GLOBALOUTNAK: break; + case GRXSTS_PKTSTS_GLOBALOUTNAK: + break; case GRXSTS_PKTSTS_SETUPRX: // Setup packet received @@ -1023,29 +915,22 @@ static void handle_rxflvl_irq(uint8_t rhport) // only the last one is valid. _setup_packet[0] = (*rx_fifo); _setup_packet[1] = (*rx_fifo); - break; + break; case GRXSTS_PKTSTS_SETUPDONE: // Setup packet done (Interrupt) epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - break; + break; - case GRXSTS_PKTSTS_OUTRX: - { - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - TU_ASSERT(epnum < ep_count, ); - + case GRXSTS_PKTSTS_OUTRX: { // Out packet received - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // Read packet off RxFIFO - if ( xfer->ff ) - { + if (xfer->ff) { // Ring buffer tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt); - } - else - { + } else { // Linear buffer read_fifo_packet(rhport, xfer->buffer, bcnt); @@ -1054,73 +939,64 @@ static void handle_rxflvl_irq(uint8_t rhport) } // Truncate transfer length in case of short packet - if ( bcnt < xfer->max_size ) - { + if (bcnt < xfer->max_size) { xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; - if ( epnum == 0 ) - { + if (epnum == 0) { xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; ep0_pending[TUSB_DIR_OUT] = 0; } } } - break; + break; - // Out packet done (Interrupt) + // Out packet done (Interrupt) case GRXSTS_PKTSTS_OUTDONE: - // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a - // May (or not) be 3.10a specific feature/bug or depending on MCU configuration - // XFRC complete is additionally generated when - // - setup packet is received - // - complete the data stage of control write is complete - if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) - { - uint32_t doepint = epout->doepint; - - if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) - { - // skip this "no-data" transfer complete event - // Note: STPKTRX will be clear later by setup received handler - uint32_t clear_flags = DOEPINT_XFRC; - - if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR; - - epout->doepint = clear_flags; - - // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n"); - } + // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a + // May (or not) be 3.10a specific feature/bug or depending on MCU configuration + // XFRC complete is additionally generated when + // - setup packet is received + // - complete the data stage of control write is complete + if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) { + uint32_t doepint = epout->doepint; + + if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) { + // skip this "no-data" transfer complete event + // Note: STPKTRX will be clear later by setup received handler + uint32_t clear_flags = DOEPINT_XFRC; + + if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR; + + epout->doepint = clear_flags; + + // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n"); } - break; + } + break; default: // Invalid TU_BREAKPOINT(); - break; + break; } } -static void handle_epout_irq (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void handle_epout_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; // DAINT for a given EP clears when DOEPINTx is cleared. // OEPINT will be cleared when DAINT's out bits are cleared. - for ( uint8_t n = 0; n < ep_count; n++ ) - { - if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) ) - { + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n)) { dwc2_epout_t* epout = &dwc2->epout[n]; uint32_t const doepint = epout->doepint; // SETUP packet Setup Phase done. - if ( doepint & DOEPINT_STUP ) - { + if (doepint & DOEPINT_STUP) { uint32_t clear_flag = DOEPINT_STUP; // STPKTRX is only available for version from 3_00a - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) - { + if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) { clear_flag |= DOEPINT_STPKTRX; } @@ -1129,20 +1005,16 @@ static void handle_epout_irq (uint8_t rhport) } // OUT XFER complete - if ( epout->doepint & DOEPINT_XFRC ) - { + if (epout->doepint & DOEPINT_XFRC) { epout->doepint = DOEPINT_XFRC; - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); // EP0 can only handle one packet - if ( (n == 0) && ep0_pending[TUSB_DIR_OUT] ) - { + if ((n == 0) && ep0_pending[TUSB_DIR_OUT]) { // Schedule another packet to be received. edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); - } - else - { + } else { dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } } @@ -1150,40 +1022,32 @@ static void handle_epout_irq (uint8_t rhport) } } -static void handle_epin_irq (uint8_t rhport) -{ - dwc2_regs_t * dwc2 = DWC2_REG(rhport); +static void handle_epin_irq(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - dwc2_epin_t* epin = dwc2->epin; + dwc2_epin_t* epin = dwc2->epin; // DAINT for a given EP clears when DIEPINTx is cleared. // IEPINT will be cleared when DAINT's out bits are cleared. - for ( uint8_t n = 0; n < ep_count; n++ ) - { - if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) ) - { + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) { // IN XFER complete (entire xfer). - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); - if ( epin[n].diepint & DIEPINT_XFRC ) - { + if (epin[n].diepint & DIEPINT_XFRC) { epin[n].diepint = DIEPINT_XFRC; // EP0 can only handle one packet - if ( (n == 0) && ep0_pending[TUSB_DIR_IN] ) - { + if ((n == 0) && ep0_pending[TUSB_DIR_IN]) { // Schedule another packet to be transmitted. edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); - } - else - { + } else { dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } } // XFER FIFO empty - if ( (epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n)) ) - { + if ((epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) { // diepint's TXFE bit is read-only, software cannot clear it. // It will only be cleared by hardware when written bytes is more than // - 64 bytes or @@ -1192,8 +1056,7 @@ static void handle_epin_irq (uint8_t rhport) uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos; // Process every single packet (only whole packets can be written to fifo) - for ( uint16_t i = 0; i < remaining_packets; i++ ) - { + for (uint16_t i = 0; i < remaining_packets; i++) { uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos; // Packet can not be larger than ep max size @@ -1201,16 +1064,13 @@ static void handle_epin_irq (uint8_t rhport) // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current // EP has to be checked if the buffer can take another WHOLE packet - if ( packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2) ) break; + if (packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) break; // Push packet to Tx-FIFO - if ( xfer->ff ) - { - volatile uint32_t *tx_fifo = dwc2->fifo[n]; + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[n]; tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size); - } - else - { + } else { write_fifo_packet(rhport, n, xfer->buffer, packet_size); // Increment pointer to xfer data @@ -1219,8 +1079,7 @@ static void handle_epin_irq (uint8_t rhport) } // Turn off TXFE if all bytes are written. - if ( ((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0 ) - { + if (((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0) { dwc2->diepempmsk &= ~(1 << n); } } @@ -1228,55 +1087,50 @@ static void handle_epin_irq (uint8_t rhport) } } -void dcd_int_handler(uint8_t rhport) -{ - dwc2_regs_t *dwc2 = DWC2_REG(rhport); +void dcd_int_handler(uint8_t rhport) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint32_t const int_mask = dwc2->gintmsk; uint32_t const int_status = dwc2->gintsts & int_mask; - if(int_status & GINTSTS_USBRST) - { + if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; bus_reset(rhport); } - if(int_status & GINTSTS_ENUMDNE) - { + if (int_status & GINTSTS_ENUMDNE) { // ENUMDNE is the end of reset where speed of the link is detected - dwc2->gintsts = GINTSTS_ENUMDNE; tusb_speed_t speed; - switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) - { + switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) { case DSTS_ENUMSPD_HS: speed = TUSB_SPEED_HIGH; - break; + break; case DSTS_ENUMSPD_LS: speed = TUSB_SPEED_LOW; - break; + break; case DSTS_ENUMSPD_FS_HSPHY: case DSTS_ENUMSPD_FS: default: speed = TUSB_SPEED_FULL; - break; + break; } + // TODO must update GUSBCFG_TRDT according to link speed + dcd_event_bus_reset(rhport, speed, true); } - if(int_status & GINTSTS_USBSUSP) - { + if (int_status & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } - if(int_status & GINTSTS_WKUINT) - { + if (int_status & GINTSTS_WKUINT) { dwc2->gintsts = GINTSTS_WKUINT; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } @@ -1284,73 +1138,52 @@ void dcd_int_handler(uint8_t rhport) // TODO check GINTSTS_DISCINT for disconnect detection // if(int_status & GINTSTS_DISCINT) - if(int_status & GINTSTS_OTGINT) - { + if (int_status & GINTSTS_OTGINT) { // OTG INT bit is read-only uint32_t const otg_int = dwc2->gotgint; - if (otg_int & GOTGINT_SEDET) - { + if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } dwc2->gotgint = otg_int; } - if(int_status & GINTSTS_SOF) - { + if(int_status & GINTSTS_SOF) { dwc2->gintsts = GINTSTS_SOF; + const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; - if (_sof_en) - { - uint32_t frame = (dwc2->dsts & (DSTS_FNSOF)) >> 8; - dcd_event_sof(rhport, frame, true); - } - else - { - // Disable SOF interrupt if SOF was not explicitly enabled. SOF was used for remote wakeup detection + // Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection + if (!_sof_en) { dwc2->gintmsk &= ~GINTMSK_SOFM; } - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + dcd_event_sof(rhport, frame, true); } // RxFIFO non-empty interrupt handling. - if(int_status & GINTSTS_RXFLVL) - { + if (int_status & GINTSTS_RXFLVL) { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // Loop until all available packets were handled - do - { + do { handle_rxflvl_irq(rhport); } while(dwc2->gintsts & GINTSTS_RXFLVL); - // Manage RX FIFO size - if (_out_ep_closed) - { - update_grxfsiz(rhport); - - // Disable flag - _out_ep_closed = false; - } - dwc2->gintmsk |= GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. - if(int_status & GINTSTS_OEPINT) - { + if (int_status & GINTSTS_OEPINT) { // OEPINT is read-only, clear using DOEPINTn handle_epout_irq(rhport); } // IN endpoint interrupt handling. - if(int_status & GINTSTS_IEPINT) - { + if (int_status & GINTSTS_IEPINT) { // IEPINT bit read-only, clear using DIEPINTn handle_epin_irq(rhport); } diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_bcm.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_bcm.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_bcm.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_bcm.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_efm32.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_efm32.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_efm32.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_efm32.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_esp32.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_esp32.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_esp32.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_esp32.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_gd32.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_gd32.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_gd32.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_gd32.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md new file mode 100644 index 00000000..8690a075 --- /dev/null +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.md @@ -0,0 +1,55 @@ +| | BCM2711 (Pi4) | EFM32GG FullSpeed | ESP32-S2 | STM32F407 Fullspeed | STM32F407 Highspeed | STM32F411 Fullspeed | STM32F412 Fullspeed | STM32F429 Fullspeed | STM32F429 Highspeed | STM32F723 Fullspeed | STM32F723 HighSpeed | STM32F767 Fullspeed | STM32H743 Highspeed | STM32L476 Fullspeed | STM32U5A5 Highspeed | GD32VF103 Fullspeed | XMC4500 | +|:----------------------------|:----------------|:--------------------|:-----------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:-----------| +| guid | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00001200 | 0x00001100 | 0x00003000 | 0x00003100 | 0x00002000 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00001000 | 0x00AEC000 | +| gsnpsid | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54281A | 0x4F54281A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x00000000 | 0x4F54292A | +| - specs version | 2.80a | 3.30a | 4.00a | 2.81a | 2.81a | 2.81a | 3.20a | 2.81a | 2.81a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 0.00W | 2.92a | +| ghwcfg1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| ghwcfg2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x229DCD20 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229FE1D0 | 0x229ED520 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x00000000 | 0x228F5930 | +| - op_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | +| - arch | 2 | 2 | 2 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | +| - point2point | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | +| - hs_phy_type | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 3 | 0 | 2 | 0 | 1 | 0 | 0 | +| - fs_phy_type | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - num_dev_ep | 7 | 6 | 6 | 3 | 5 | 3 | 5 | 3 | 5 | 5 | 8 | 5 | 8 | 5 | 8 | 0 | 6 | +| - num_host_ch | 7 | 13 | 7 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 15 | 11 | 15 | 11 | 15 | 0 | 13 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - mul_cpu_int | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nperiod_tx_q_depth | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 | +| - host_period_tx_q_depth | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 | +| - dev_token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 8 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| ghwcfg3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x020001E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x03EED2E8 | 0x0200D1E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x00000000 | 0x027A01E5 | +| - xfer_size_width | 8 | 8 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 5 | +| - packet_size_width | 6 | 6 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | 6 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - i2c_enable | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | +| - vendor_ctrl_itf | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - total_fifo_size | 4080 | 498 | 200 | 512 | 1012 | 512 | 512 | 512 | 1012 | 512 | 1006 | 512 | 952 | 512 | 952 | 0 | 634 | +| ghwcfg4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0x0FF08030 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x23F00030 | 0x17F08030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0x00000000 | 0xDBF08030 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - power_optimized | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 0 | 0 | +| - service_interval_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_en | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - reserved13 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - utmi_phy_data_width | 0 | 2 | 2 | 2 | 0 | 2 | 2 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 0 | 2 | +| - dev_ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | +| - vbus_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - a_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - b_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | +| - num_dev_in_eps | 15 | 13 | 9 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 1 | 11 | 1 | 11 | 1 | 0 | 13 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | +| - dma_dynamic | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | diff --git a/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py new file mode 100644 index 00000000..55bec3d2 --- /dev/null +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_info.py @@ -0,0 +1,169 @@ +import click +import ctypes +import pandas as pd + +# hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 +dwc2_reg_list = ['guid', 'gsnpsid', 'ghwcfg1', 'ghwcfg2', 'ghwcfg3', 'ghwcfg4'] +dwc2_reg_value = { + 'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020], + 'EFM32GG FullSpeed': [0, 0x4F54330A, 0, 0x228F5910, 0x1F204E8, 0x1BF08030], + 'ESP32-S2': [0, 0x4F54400A, 0, 0x224DD930, 0xC804B5, 0xD3F0A030], + 'STM32F407 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F407 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030], + 'STM32F411 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F412 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32F429 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030], + 'STM32F429 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030], + 'STM32F723 Fullspeed': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32F723 HighSpeed': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x3EED2E8, 0x23F00030], + 'STM32F767 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32H743 Highspeed': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x3B8D2E8, 0xE3F00030], # both HS cores + 'STM32L476 Fullspeed': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x200D1E8, 0x17F08030], + 'STM32U5A5 Highspeed': [0x00005000, 0x4F54411A, 0x00000000, 0x228FE052, 0x03B882E8, 0xE2103E30], + 'GD32VF103 Fullspeed': [0x1000, 0, 0, 0, 0, 0], + 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x27A01E5, 0xDBF08030] +} + +# Combine dwc2_info with dwc2_reg_list +# dwc2_info = { +# 'BCM2711 (Pi4)': { +# 'guid': 0x2708A000, +# 'gsnpsid': 0x4F54280A, +# 'ghwcfg1': 0, +# 'ghwcfg2': 0x228DDD50, +# 'ghwcfg3': 0xFF000E8, +# 'ghwcfg4': 0x1FF00020 +# }, +dwc2_info = {key: {field: value for field, value in zip(dwc2_reg_list, values)} for key, values in dwc2_reg_value.items()} + + +class GHWCFG2(ctypes.LittleEndianStructure): + _fields_ = [ + ("op_mode", ctypes.c_uint32, 3), + ("arch", ctypes.c_uint32, 2), + ("point2point", ctypes.c_uint32, 1), + ("hs_phy_type", ctypes.c_uint32, 2), + ("fs_phy_type", ctypes.c_uint32, 2), + ("num_dev_ep", ctypes.c_uint32, 4), + ("num_host_ch", ctypes.c_uint32, 4), + ("period_channel_support", ctypes.c_uint32, 1), + ("enable_dynamic_fifo", ctypes.c_uint32, 1), + ("mul_cpu_int", ctypes.c_uint32, 1), + ("reserved21", ctypes.c_uint32, 1), + ("nperiod_tx_q_depth", ctypes.c_uint32, 2), + ("host_period_tx_q_depth", ctypes.c_uint32, 2), + ("dev_token_q_depth", ctypes.c_uint32, 5), + ("otg_enable_ic_usb", ctypes.c_uint32, 1) + ] + + +class GHWCFG3(ctypes.LittleEndianStructure): + _fields_ = [ + ("xfer_size_width", ctypes.c_uint32, 4), + ("packet_size_width", ctypes.c_uint32, 3), + ("otg_enable", ctypes.c_uint32, 1), + ("i2c_enable", ctypes.c_uint32, 1), + ("vendor_ctrl_itf", ctypes.c_uint32, 1), + ("optional_feature_removed", ctypes.c_uint32, 1), + ("synch_reset", ctypes.c_uint32, 1), + ("otg_adp_support", ctypes.c_uint32, 1), + ("otg_enable_hsic", ctypes.c_uint32, 1), + ("battery_charger_support", ctypes.c_uint32, 1), + ("lpm_mode", ctypes.c_uint32, 1), + ("total_fifo_size", ctypes.c_uint32, 16) + ] + + +class GHWCFG4(ctypes.LittleEndianStructure): + _fields_ = [ + ("num_dev_period_in_ep", ctypes.c_uint32, 4), + ("power_optimized", ctypes.c_uint32, 1), + ("ahb_freq_min", ctypes.c_uint32, 1), + ("hibernation", ctypes.c_uint32, 1), + ("reserved7", ctypes.c_uint32, 3), + ("service_interval_mode", ctypes.c_uint32, 1), + ("ipg_isoc_en", ctypes.c_uint32, 1), + ("acg_enable", ctypes.c_uint32, 1), + ("reserved13", ctypes.c_uint32, 1), + ("utmi_phy_data_width", ctypes.c_uint32, 2), + ("dev_ctrl_ep_num", ctypes.c_uint32, 4), + ("iddg_filter_enabled", ctypes.c_uint32, 1), + ("vbus_valid_filter_enabled", ctypes.c_uint32, 1), + ("a_valid_filter_enabled", ctypes.c_uint32, 1), + ("b_valid_filter_enabled", ctypes.c_uint32, 1), + ("dedicated_fifos", ctypes.c_uint32, 1), + ("num_dev_in_eps", ctypes.c_uint32, 4), + ("dma_desc_enable", ctypes.c_uint32, 1), + ("dma_dynamic", ctypes.c_uint32, 1) + ] + + +@click.group() +def cli(): + pass + + +@cli.command() +@click.argument('mcus', nargs=-1) +@click.option('-a', '--all', is_flag=True, help='Print all bit-field values') +def info(mcus, all): + """Print DWC2 register values for given MCU(s)""" + if len(mcus) == 0: + mcus = dwc2_info + + for mcu in mcus: + for entry in dwc2_info: + if mcu.lower() in entry.lower(): + print(f"## {entry}") + for r_name, r_value in dwc2_info[entry].items(): + print(f"{r_name} = 0x{r_value:08X}") + # Print bit-field values + if all and r_name.upper() in globals(): + class_name = globals()[r_name.upper()] + ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little')) + for field_name, field_type, _ in class_name._fields_: + print(f" {field_name} = {getattr(ghwcfg, field_name)}") + + +@cli.command() +def render_md(): + """Render dwc2_info to Markdown table""" + # Create an empty list to hold the dictionaries + dwc2_info_list = [] + + # Iterate over the dwc2_info dictionary and extract fields + for device, reg_values in dwc2_info.items(): + entry_dict = {"Device": device} + for r_name, r_value in reg_values.items(): + entry_dict[r_name] = f"0x{r_value:08X}" + + if r_name == 'gsnpsid': + # Get dwc2 specs version + major = ((r_value >> 8) >> 4) & 0x0F + minor = (r_value >> 4) & 0xFF + patch = chr((r_value & 0x0F) + ord('a') - 0xA) + entry_dict[f' - specs version'] = f"{major:X}.{minor:02X}{patch}" + elif r_name.upper() in globals(): + # Get bit-field values which exist as ctypes structures + class_name = globals()[r_name.upper()] + ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little')) + for field_name, field_type, _ in class_name._fields_: + entry_dict[f' - {field_name}'] = getattr(ghwcfg, field_name) + + dwc2_info_list.append(entry_dict) + + # Create a Pandas DataFrame from the list of dictionaries + df = pd.DataFrame(dwc2_info_list).set_index('Device') + + # Transpose the DataFrame to switch rows and columns + df = df.T + #print(df) + + # Write the Markdown table to a file + with open('dwc2_info.md', 'w') as md_file: + md_file.write(df.to_markdown()) + md_file.write('\n') + + +if __name__ == '__main__': + cli() diff --git a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_stm32.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h similarity index 63% rename from test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_stm32.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h index cb455bd9..3237a50f 100644 --- a/test-devices/composite-stm32/lib/tinyusb/dwc2/dwc2_stm32.h +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_stm32.h @@ -24,11 +24,11 @@ * This file is part of the TinyUSB stack. */ -#ifndef _DWC2_STM32_H_ -#define _DWC2_STM32_H_ +#ifndef DWC2_STM32_H_ +#define DWC2_STM32_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif // EP_MAX : Max number of bi-directional endpoints including EP0 @@ -84,10 +84,16 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" - #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 - + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY + #ifdef USB_OTG_FS + #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + #else + #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 + #endif #else #error "Unsupported MCUs" #endif @@ -101,15 +107,14 @@ // On STM32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS -static const dwc2_controller_t _dwc2_controller[] = -{ -#ifdef USB_OTG_FS_PERIPH_BASE - { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, -#endif - -#ifdef USB_OTG_HS_PERIPH_BASE - { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS }, -#endif +static const dwc2_controller_t _dwc2_controller[] = { + #ifdef USB_OTG_FS_PERIPH_BASE + { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + #endif + + #ifdef USB_OTG_HS_PERIPH_BASE + { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS }, + #endif }; //--------------------------------------------------------------------+ @@ -119,42 +124,59 @@ static const dwc2_controller_t _dwc2_controller[] = // SystemCoreClock is already included by family header // extern uint32_t SystemCoreClock; -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_enable(uint8_t rhport) -{ - NVIC_EnableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum); +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { + NVIC_EnableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum); } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_disable (uint8_t rhport) -{ - NVIC_DisableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum); +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum); } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_remote_wakeup_delay(void) -{ +TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while ( count-- ) __NOP(); + while (count--) __NOP(); } // MCU specific PHY init, called BEFORE core reset -static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ - if ( hs_phy_type == HS_PHY_TYPE_NONE ) - { +// - dwc2 3.30a (H5) use USB_HS_PHYC +// - dwc2 4.11a (U5) use femtoPHY +static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { + if (hs_phy_type == HS_PHY_TYPE_NONE) { // Enable on-chip FS PHY dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN; - }else - { - // Disable FS PHY + + // https://community.st.com/t5/stm32cubemx-mcus/why-stm32h743-usb-fs-doesn-t-work-if-freertos-tickless-idle/m-p/349480#M18867 + // H7 running on full-speed phy need to disable ULPI clock in sleep mode. + // Otherwise, USB won't work when mcu executing WFI/WFE instruction i.e tick-less RTOS. + // Note: there may be other family that is affected by this, but only H7 and F7 is tested so far + #if defined(USB_OTG_FS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB2OTGFSULPILPEN) + if ( USB_OTG_FS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB2OTGFSULPILPEN; + } + #endif + + #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB1OTGHSULPILPEN) + if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB1OTGHSULPILPEN; + } + #endif + + #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_OTGHSULPILPEN) + if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) { + RCC->AHB1LPENR &= ~RCC_AHB1LPENR_OTGHSULPILPEN; + } + #endif + + } else { +#if CFG_TUSB_MCU != OPT_MCU_STM32U5 + // Disable FS PHY, TODO on U5A5 (dwc2 4.11a) 16th bit is 'Host CDP behavior enable' dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; +#endif // Enable on-chip HS PHY - if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) - { -#ifdef USB_HS_PHYC + if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) { + #ifdef USB_HS_PHYC // Enable UTMI HS PHY dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN; @@ -186,40 +208,47 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) // Enable PLL internal PHY USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; -#endif + #else + + #endif } } } // MCU specific PHY update, it is called AFTER init() and core reset -static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ +static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { // used to set turnaround time for fullspeed, nothing to do in highspeed mode - if ( hs_phy_type == HS_PHY_TYPE_NONE ) - { + if (hs_phy_type == HS_PHY_TYPE_NONE) { // Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual uint32_t turnaround; - if ( SystemCoreClock >= 32000000u ) + if (SystemCoreClock >= 32000000u) { turnaround = 0x6u; - else if ( SystemCoreClock >= 27500000u ) + } else if (SystemCoreClock >= 27500000u) { turnaround = 0x7u; - else if ( SystemCoreClock >= 24000000u ) + } else if (SystemCoreClock >= 24000000u) { turnaround = 0x8u; - else if ( SystemCoreClock >= 21800000u ) + } else if (SystemCoreClock >= 21800000u) { turnaround = 0x9u; - else if ( SystemCoreClock >= 20000000u ) + } + else if (SystemCoreClock >= 20000000u) { turnaround = 0xAu; - else if ( SystemCoreClock >= 18500000u ) + } + else if (SystemCoreClock >= 18500000u) { turnaround = 0xBu; - else if ( SystemCoreClock >= 17200000u ) + } + else if (SystemCoreClock >= 17200000u) { turnaround = 0xCu; - else if ( SystemCoreClock >= 16000000u ) + } + else if (SystemCoreClock >= 16000000u) { turnaround = 0xDu; - else if ( SystemCoreClock >= 15000000u ) + } + else if (SystemCoreClock >= 15000000u) { turnaround = 0xEu; - else + } + else { turnaround = 0xFu; + } dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos); } @@ -229,4 +258,4 @@ static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) } #endif -#endif /* _DWC2_STM32_H_ */ +#endif diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_type.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h similarity index 71% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_type.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h index 3fc97933..c1577123 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_type.h +++ b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_type.h @@ -32,7 +32,7 @@ typedef struct uint32_t ep_fifo_size; }dwc2_controller_t; -/* DWC OTG HW Release versions */ +// DWC OTG HW Release versions #define DWC2_CORE_REV_2_71a 0x4f54271a #define DWC2_CORE_REV_2_72a 0x4f54272a #define DWC2_CORE_REV_2_80a 0x4f54280a @@ -43,12 +43,13 @@ typedef struct #define DWC2_CORE_REV_3_00a 0x4f54300a #define DWC2_CORE_REV_3_10a 0x4f54310a #define DWC2_CORE_REV_4_00a 0x4f54400a +#define DWC2_CORE_REV_4_11a 0x4f54411a #define DWC2_CORE_REV_4_20a 0x4f54420a #define DWC2_FS_IOT_REV_1_00a 0x5531100a #define DWC2_HS_IOT_REV_1_00a 0x5532100a #define DWC2_CORE_REV_MASK 0x0000ffff -/* DWC OTG HW Core ID */ +// DWC OTG HW Core ID #define DWC2_OTG_ID 0x4f540000 #define DWC2_FS_IOT_ID 0x55310000 #define DWC2_HS_IOT_ID 0x55320000 @@ -57,13 +58,13 @@ typedef struct // HS PHY typedef struct { - volatile uint32_t HS_PHYC_PLL; // This register is used to control the PLL of the HS PHY. 000h */ - volatile uint32_t Reserved04; // Reserved 004h */ - volatile uint32_t Reserved08; // Reserved 008h */ - volatile uint32_t HS_PHYC_TUNE; // This register is used to control the tuning interface of the High Speed PHY. 00Ch */ - volatile uint32_t Reserved10; // Reserved 010h */ - volatile uint32_t Reserved14; // Reserved 014h */ - volatile uint32_t HS_PHYC_LDO; // This register is used to control the regulator (LDO). 018h */ + volatile uint32_t HS_PHYC_PLL; // 000h This register is used to control the PLL of the HS PHY. + volatile uint32_t Reserved04; // 004h Reserved + volatile uint32_t Reserved08; // 008h Reserved + volatile uint32_t HS_PHYC_TUNE; // 00Ch This register is used to control the tuning interface of the High Speed PHY. + volatile uint32_t Reserved10; // 010h Reserved + volatile uint32_t Reserved14; // 014h Reserved + volatile uint32_t HS_PHYC_LDO; // 018h This register is used to control the regulator (LDO). } HS_PHYC_GlobalTypeDef; #endif @@ -298,103 +299,103 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); /******************** Bit definition for GOTGCTL register ********************/ #define GOTGCTL_SRQSCS_Pos (0U) -#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 */ -#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success */ +#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 +#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success #define GOTGCTL_SRQ_Pos (1U) -#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 */ -#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request */ +#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 +#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request #define GOTGCTL_VBVALOEN_Pos (2U) -#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 */ -#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable */ +#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 +#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable #define GOTGCTL_VBVALOVAL_Pos (3U) -#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 */ -#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value */ +#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 +#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value #define GOTGCTL_AVALOEN_Pos (4U) -#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 */ -#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable */ +#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 +#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable #define GOTGCTL_AVALOVAL_Pos (5U) -#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 */ -#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value */ +#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 +#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value #define GOTGCTL_BVALOEN_Pos (6U) -#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 */ -#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable */ +#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 +#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable #define GOTGCTL_BVALOVAL_Pos (7U) -#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 */ -#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value */ +#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 +#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value #define GOTGCTL_HNGSCS_Pos (8U) -#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 */ -#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable */ +#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 +#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable #define GOTGCTL_HNPRQ_Pos (9U) -#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 */ -#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request */ +#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 +#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request #define GOTGCTL_HSHNPEN_Pos (10U) -#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 */ -#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable */ +#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 +#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable #define GOTGCTL_DHNPEN_Pos (11U) -#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 */ -#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled */ +#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 +#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled #define GOTGCTL_EHEN_Pos (12U) -#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 */ -#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable */ +#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 +#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable #define GOTGCTL_CIDSTS_Pos (16U) -#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 */ -#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status */ +#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 +#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status #define GOTGCTL_DBCT_Pos (17U) -#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 */ -#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time */ +#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 +#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time #define GOTGCTL_ASVLD_Pos (18U) -#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 */ -#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid */ +#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 +#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid #define GOTGCTL_BSESVLD_Pos (19U) -#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 */ -#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid */ +#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 +#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid #define GOTGCTL_OTGVER_Pos (20U) -#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 */ -#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version */ +#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 +#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version /******************** Bit definition for HCFG register ********************/ #define HCFG_FSLSPCS_Pos (0U) -#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 */ -#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select */ -#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 */ -#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 */ +#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 +#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select +#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 +#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 #define HCFG_FSLSS_Pos (2U) -#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 */ -#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support */ +#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 +#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support /******************** Bit definition for PCGCR register ********************/ #define PCGCR_STPPCLK_Pos (0U) -#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 */ -#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock */ +#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 +#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock #define PCGCR_GATEHCLK_Pos (1U) -#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 */ -#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK */ +#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 +#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK #define PCGCR_PHYSUSP_Pos (4U) -#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 */ -#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended */ +#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 +#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended /******************** Bit definition for GOTGINT register ********************/ #define GOTGINT_SEDET_Pos (2U) -#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 */ -#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected */ +#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 +#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected #define GOTGINT_SRSSCHG_Pos (8U) -#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 */ -#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change */ +#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 +#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change #define GOTGINT_HNSSCHG_Pos (9U) -#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 */ -#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change */ +#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 +#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change #define GOTGINT_HNGDET_Pos (17U) -#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 */ -#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected */ +#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 +#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected #define GOTGINT_ADTOCHG_Pos (18U) -#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 */ -#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change */ +#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 +#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change #define GOTGINT_DBCDNE_Pos (19U) -#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 */ -#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done */ +#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 +#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done #define GOTGINT_IDCHNG_Pos (20U) -#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 */ -#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value */ +#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 +#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value /******************** Bit definition for DCFG register ********************/ #define DCFG_DSPD_Pos (0U) @@ -405,92 +406,92 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DCFG_DSPD_FS 3 // Fullspeed on FS PHY #define DCFG_NZLSOHSK_Pos (2U) -#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 */ -#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake */ +#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 +#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake #define DCFG_DAD_Pos (4U) -#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 */ -#define DCFG_DAD DCFG_DAD_Msk // Device address */ -#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 */ -#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 */ -#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 */ -#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 */ -#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 */ -#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 */ -#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 */ +#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 +#define DCFG_DAD DCFG_DAD_Msk // Device address +#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 +#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 +#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 +#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 +#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 +#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 +#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 #define DCFG_PFIVL_Pos (11U) -#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 */ -#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval */ -#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 */ -#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 */ +#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 +#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval +#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 +#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 #define DCFG_XCVRDLY_Pos (14U) -#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) /*!< 0x00004000 */ +#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) // 0x00004000 #define DCFG_XCVRDLY DCFG_XCVRDLY_Msk // Enables delay between xcvr_sel and txvalid during device chirp #define DCFG_PERSCHIVL_Pos (24U) -#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 */ -#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval */ -#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 */ -#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 */ +#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 +#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval +#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 +#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 /******************** Bit definition for DCTL register ********************/ #define DCTL_RWUSIG_Pos (0U) -#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 */ -#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling */ +#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 +#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling #define DCTL_SDIS_Pos (1U) -#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 */ -#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect */ +#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 +#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect #define DCTL_GINSTS_Pos (2U) -#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 */ -#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status */ +#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 +#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status #define DCTL_GONSTS_Pos (3U) -#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 */ -#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status */ +#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 +#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status #define DCTL_TCTL_Pos (4U) -#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 */ -#define DCTL_TCTL DCTL_TCTL_Msk // Test control */ -#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 */ -#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 */ -#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 */ +#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 +#define DCTL_TCTL DCTL_TCTL_Msk // Test control +#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 +#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 +#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 #define DCTL_SGINAK_Pos (7U) -#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 */ -#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK */ +#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 +#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK #define DCTL_CGINAK_Pos (8U) -#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 */ -#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK */ +#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 +#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK #define DCTL_SGONAK_Pos (9U) -#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 */ -#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK */ +#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 +#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK #define DCTL_CGONAK_Pos (10U) -#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 */ -#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK */ +#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 +#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK #define DCTL_POPRGDNE_Pos (11U) -#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 */ -#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done */ +#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 +#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done /******************** Bit definition for HFIR register ********************/ #define HFIR_FRIVL_Pos (0U) -#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF */ -#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval */ +#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF +#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval /******************** Bit definition for HFNUM register ********************/ #define HFNUM_FRNUM_Pos (0U) -#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF */ -#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number */ +#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF +#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number #define HFNUM_FTREM_Pos (16U) -#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 */ -#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining */ +#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 +#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining /******************** Bit definition for DSTS register ********************/ #define DSTS_SUSPSTS_Pos (0U) -#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 */ -#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status */ +#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 +#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status #define DSTS_ENUMSPD_Pos (1U) -#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 */ -#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed */ +#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 +#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed #define DSTS_ENUMSPD_HS 0 // Highspeed #define DSTS_ENUMSPD_FS_HSPHY 1 // Fullspeed on HS PHY #define DSTS_ENUMSPD_LS 2 // Lowspeed @@ -498,427 +499,427 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DSTS_EERR_Pos (3U) -#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 */ -#define DSTS_EERR DSTS_EERR_Msk // Erratic error */ +#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 +#define DSTS_EERR DSTS_EERR_Msk // Erratic error #define DSTS_FNSOF_Pos (8U) -#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 */ -#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF */ +#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 +#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF /******************** Bit definition for GAHBCFG register ********************/ #define GAHBCFG_GINT_Pos (0U) -#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 */ -#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask */ +#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 +#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask #define GAHBCFG_HBSTLEN_Pos (1U) -#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E */ -#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type */ -#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single */ -#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR */ -#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 */ -#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 */ -#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 */ +#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E +#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type +#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single +#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR +#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 +#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 +#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 #define GAHBCFG_DMAEN_Pos (5U) -#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 */ -#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable */ +#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 +#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable #define GAHBCFG_TXFELVL_Pos (7U) -#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 */ -#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level */ +#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 +#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level #define GAHBCFG_PTXFELVL_Pos (8U) -#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 */ -#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level */ +#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 +#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level #define GSNPSID_ID_MASK TU_GENMASK(31, 16) /******************** Bit definition for GUSBCFG register ********************/ #define GUSBCFG_TOCAL_Pos (0U) -#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 */ -#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration */ +#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 +#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration #define GUSBCFG_PHYIF16_Pos (3U) -#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 */ -#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) */ +#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 +#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) #define GUSBCFG_ULPI_UTMI_SEL_Pos (4U) -#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 */ -#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) */ +#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 +#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) #define GUSBCFG_PHYSEL_Pos (6U) -#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 */ -#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ +#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 +#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select #define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface. #define GUSBCFG_SRPCAP_Pos (8U) -#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 */ -#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable */ +#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 +#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable #define GUSBCFG_HNPCAP_Pos (9U) -#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 */ -#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable */ +#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 +#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable #define GUSBCFG_TRDT_Pos (10U) -#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 */ -#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time */ +#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 +#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time #define GUSBCFG_PHYLPCS_Pos (15U) -#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 */ -#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select */ +#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 +#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select #define GUSBCFG_ULPIFSLS_Pos (17U) -#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 */ -#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select */ +#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 +#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select #define GUSBCFG_ULPIAR_Pos (18U) -#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 */ -#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume */ +#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 +#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume #define GUSBCFG_ULPICSM_Pos (19U) -#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 */ -#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM */ +#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 +#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM #define GUSBCFG_ULPIEVBUSD_Pos (20U) -#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 */ -#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive */ +#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 +#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive #define GUSBCFG_ULPIEVBUSI_Pos (21U) -#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 */ -#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator */ +#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 +#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator #define GUSBCFG_TSDPS_Pos (22U) -#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 */ -#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection */ +#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 +#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection #define GUSBCFG_PCCI_Pos (23U) -#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 */ -#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement */ +#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 +#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement #define GUSBCFG_PTCI_Pos (24U) -#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 */ -#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through */ +#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 +#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through #define GUSBCFG_ULPIIPD_Pos (25U) -#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 */ -#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable */ +#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 +#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable #define GUSBCFG_FHMOD_Pos (29U) -#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 */ -#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode */ +#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 +#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode #define GUSBCFG_FDMOD_Pos (30U) -#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 */ -#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode */ +#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 +#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode #define GUSBCFG_CTXPKT_Pos (31U) -#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 */ -#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet */ +#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 +#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet /******************** Bit definition for GRSTCTL register ********************/ #define GRSTCTL_CSRST_Pos (0U) -#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 */ -#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset */ +#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 +#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset #define GRSTCTL_HSRST_Pos (1U) -#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 */ -#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset */ +#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 +#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset #define GRSTCTL_FCRST_Pos (2U) -#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 */ -#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset */ +#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 +#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset #define GRSTCTL_RXFFLSH_Pos (4U) -#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 */ -#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush */ +#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 +#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush #define GRSTCTL_TXFFLSH_Pos (5U) -#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 */ -#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush */ +#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 +#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush #define GRSTCTL_TXFNUM_Pos (6U) -#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 */ -#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number */ -#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 */ -#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 */ -#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 */ -#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 */ -#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 */ +#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 +#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number +#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 +#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 +#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 +#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 +#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 #define GRSTCTL_CSFTRST_DONE_Pos (29) #define GRSTCTL_CSFTRST_DONE (1u << GRSTCTL_CSFTRST_DONE_Pos) // Reset Done, only available from v4.20a #define GRSTCTL_DMAREQ_Pos (30U) -#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 */ -#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal */ +#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 +#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal #define GRSTCTL_AHBIDL_Pos (31U) -#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 */ -#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle */ +#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 +#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle /******************** Bit definition for DIEPMSK register ********************/ #define DIEPMSK_XFRCM_Pos (0U) -#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 */ -#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 +#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask #define DIEPMSK_EPDM_Pos (1U) -#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 */ -#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 +#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask #define DIEPMSK_TOM_Pos (3U) -#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 */ -#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 +#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) #define DIEPMSK_ITTXFEMSK_Pos (4U) -#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 */ -#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 +#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DIEPMSK_INEPNMM_Pos (5U) -#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 */ -#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 +#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask #define DIEPMSK_INEPNEM_Pos (6U) -#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 */ -#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 +#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask #define DIEPMSK_TXFURM_Pos (8U) -#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 */ -#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask */ +#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 +#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask #define DIEPMSK_BIM_Pos (9U) -#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 */ -#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask */ +#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 +#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask /******************** Bit definition for HPTXSTS register ********************/ #define HPTXSTS_PTXFSAVL_Pos (0U) -#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF */ -#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available */ +#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF +#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available #define HPTXSTS_PTXQSAV_Pos (16U) -#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 */ -#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available */ -#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 */ -#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 */ -#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 */ -#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 */ -#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 */ -#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 */ -#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 */ -#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 */ +#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 +#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available +#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 +#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 +#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 +#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 +#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 +#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 +#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 +#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 #define HPTXSTS_PTXQTOP_Pos (24U) -#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 */ -#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue */ -#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 */ -#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 */ -#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 */ -#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 */ -#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 */ -#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 */ -#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 */ -#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 */ +#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 +#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue +#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 +#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 +#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 +#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 +#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 +#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 +#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 +#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 /******************** Bit definition for HAINT register ********************/ #define HAINT_HAINT_Pos (0U) -#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF */ -#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts */ +#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF +#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts /******************** Bit definition for DOEPMSK register ********************/ #define DOEPMSK_XFRCM_Pos (0U) -#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 */ -#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 +#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask #define DOEPMSK_EPDM_Pos (1U) -#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 */ -#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 +#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask #define DOEPMSK_AHBERRM_Pos (2U) -#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 */ -#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask */ +#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 +#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask #define DOEPMSK_STUPM_Pos (3U) -#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 */ -#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask */ +#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 +#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask #define DOEPMSK_OTEPDM_Pos (4U) -#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 */ -#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask */ +#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 +#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask #define DOEPMSK_OTEPSPRM_Pos (5U) -#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 */ -#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask */ +#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 +#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask #define DOEPMSK_B2BSTUP_Pos (6U) -#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 */ -#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask */ +#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 +#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask #define DOEPMSK_OPEM_Pos (8U) -#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 */ -#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask */ +#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 +#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask #define DOEPMSK_BOIM_Pos (9U) -#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 */ -#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask */ +#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 +#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask #define DOEPMSK_BERRM_Pos (12U) -#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 */ -#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask */ +#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 +#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask #define DOEPMSK_NAKM_Pos (13U) -#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 */ -#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask */ +#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 +#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask #define DOEPMSK_NYETM_Pos (14U) -#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 */ -#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask */ +#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 +#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask /******************** Bit definition for GINTSTS register ********************/ #define GINTSTS_CMOD_Pos (0U) -#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 */ -#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation */ +#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 +#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation #define GINTSTS_MMIS_Pos (1U) -#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 */ -#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt */ +#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 +#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt #define GINTSTS_OTGINT_Pos (2U) -#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 */ -#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt */ +#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 +#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt #define GINTSTS_SOF_Pos (3U) -#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 */ -#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame */ +#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 +#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame #define GINTSTS_RXFLVL_Pos (4U) -#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 */ -#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty */ +#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 +#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty #define GINTSTS_NPTXFE_Pos (5U) -#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 */ -#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty */ +#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 +#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty #define GINTSTS_GINAKEFF_Pos (6U) -#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 */ -#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective */ +#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 +#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective #define GINTSTS_BOUTNAKEFF_Pos (7U) -#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 */ -#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective */ +#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 +#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective #define GINTSTS_ESUSP_Pos (10U) -#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 */ -#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend */ +#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 +#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend #define GINTSTS_USBSUSP_Pos (11U) -#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 */ -#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend */ +#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 +#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend #define GINTSTS_USBRST_Pos (12U) -#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 */ -#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset */ +#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 +#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset #define GINTSTS_ENUMDNE_Pos (13U) -#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 */ -#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done */ +#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 +#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done #define GINTSTS_ISOODRP_Pos (14U) -#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 */ -#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt */ +#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 +#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt #define GINTSTS_EOPF_Pos (15U) -#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 */ -#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt */ +#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 +#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt #define GINTSTS_IEPINT_Pos (18U) -#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 */ -#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt */ +#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 +#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt #define GINTSTS_OEPINT_Pos (19U) -#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 */ -#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt */ +#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 +#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt #define GINTSTS_IISOIXFR_Pos (20U) -#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 */ -#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer */ +#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 +#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer #define GINTSTS_PXFR_INCOMPISOOUT_Pos (21U) -#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 */ -#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer */ +#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 +#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer #define GINTSTS_DATAFSUSP_Pos (22U) -#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 */ -#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended */ +#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 +#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended #define GINTSTS_RSTDET_Pos (23U) -#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 */ -#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt */ +#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 +#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt #define GINTSTS_HPRTINT_Pos (24U) -#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 */ -#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt */ +#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 +#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt #define GINTSTS_HCINT_Pos (25U) -#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 */ -#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt */ +#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 +#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt #define GINTSTS_PTXFE_Pos (26U) -#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 */ -#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty */ +#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 +#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty #define GINTSTS_LPMINT_Pos (27U) -#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 */ -#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt */ +#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 +#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt #define GINTSTS_CIDSCHG_Pos (28U) -#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 */ -#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change */ +#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 +#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change #define GINTSTS_DISCINT_Pos (29U) -#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 */ -#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt */ +#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 +#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt #define GINTSTS_SRQINT_Pos (30U) -#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 */ -#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt */ +#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 +#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt #define GINTSTS_WKUINT_Pos (31U) -#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 */ -#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt */ +#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 +#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt /******************** Bit definition for GINTMSK register ********************/ #define GINTMSK_MMISM_Pos (1U) -#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 */ -#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask */ +#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 +#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask #define GINTMSK_OTGINT_Pos (2U) -#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 */ -#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask */ +#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 +#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask #define GINTMSK_SOFM_Pos (3U) -#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 */ -#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask */ +#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 +#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask #define GINTMSK_RXFLVLM_Pos (4U) -#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 */ -#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask */ +#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 +#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask #define GINTMSK_NPTXFEM_Pos (5U) -#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 */ -#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask */ +#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 +#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask #define GINTMSK_GINAKEFFM_Pos (6U) -#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 */ -#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask */ +#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 +#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask #define GINTMSK_GONAKEFFM_Pos (7U) -#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 */ -#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask */ +#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 +#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask #define GINTMSK_ESUSPM_Pos (10U) -#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 */ -#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask */ +#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 +#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask #define GINTMSK_USBSUSPM_Pos (11U) -#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 */ -#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask */ +#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 +#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask #define GINTMSK_USBRST_Pos (12U) -#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 */ -#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask */ +#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 +#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask #define GINTMSK_ENUMDNEM_Pos (13U) -#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 */ -#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask */ +#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 +#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask #define GINTMSK_ISOODRPM_Pos (14U) -#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 */ -#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask */ +#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 +#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask #define GINTMSK_EOPFM_Pos (15U) -#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 */ -#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask */ +#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 +#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask #define GINTMSK_EPMISM_Pos (17U) -#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 */ -#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask */ +#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 +#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask #define GINTMSK_IEPINT_Pos (18U) -#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 */ -#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask */ +#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 +#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask #define GINTMSK_OEPINT_Pos (19U) -#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 */ -#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask */ +#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 +#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask #define GINTMSK_IISOIXFRM_Pos (20U) -#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 */ -#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask */ +#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 +#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask #define GINTMSK_PXFRM_IISOOXFRM_Pos (21U) -#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 */ -#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask */ +#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 +#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask #define GINTMSK_FSUSPM_Pos (22U) -#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 */ -#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask */ +#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 +#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask #define GINTMSK_RSTDEM_Pos (23U) -#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 */ -#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask */ +#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 +#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask #define GINTMSK_PRTIM_Pos (24U) -#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 */ -#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask */ +#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 +#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask #define GINTMSK_HCIM_Pos (25U) -#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 */ -#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask */ +#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 +#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask #define GINTMSK_PTXFEM_Pos (26U) -#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 */ -#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask */ +#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 +#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask #define GINTMSK_LPMINTM_Pos (27U) -#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 */ -#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask */ +#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 +#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask #define GINTMSK_CIDSCHGM_Pos (28U) -#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 */ -#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask */ +#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 +#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask #define GINTMSK_DISCINT_Pos (29U) -#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 */ -#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask */ +#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 +#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask #define GINTMSK_SRQIM_Pos (30U) -#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 */ -#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask */ +#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 +#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask #define GINTMSK_WUIM_Pos (31U) -#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 */ -#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask */ +#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 +#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask /******************** Bit definition for DAINT register ********************/ #define DAINT_IEPINT_Pos (0U) -#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF */ -#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits */ +#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF +#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits #define DAINT_OEPINT_Pos (16U) -#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 */ -#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits */ +#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 +#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits /******************** Bit definition for HAINTMSK register ********************/ #define HAINTMSK_HAINTM_Pos (0U) -#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF */ -#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask */ +#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF +#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask /******************** Bit definition for GRXSTSP register ********************/ #define GRXSTSP_EPNUM_Pos (0U) -#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F */ -#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits */ +#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F +#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits #define GRXSTSP_BCNT_Pos (4U) -#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 */ -#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 +#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits #define GRXSTSP_DPID_Pos (15U) -#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 */ -#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 +#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits #define GRXSTSP_PKTSTS_Pos (17U) -#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 */ -#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits */ +#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 +#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits #define GRXSTS_PKTSTS_GLOBALOUTNAK 1 #define GRXSTS_PKTSTS_OUTRX 2 @@ -933,773 +934,803 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); /******************** Bit definition for DAINTMSK register ********************/ #define DAINTMSK_IEPM_Pos (0U) -#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF */ -#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits */ +#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF +#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits #define DAINTMSK_OEPM_Pos (16U) -#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 */ -#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits */ +#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 +#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits #if 0 /******************** Bit definition for OTG register ********************/ #define CHNUM_Pos (0U) -#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F */ -#define CHNUM CHNUM_Msk // Channel number */ -#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 */ -#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 */ -#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 */ -#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 */ +#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F +#define CHNUM CHNUM_Msk // Channel number +#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 +#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 +#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 +#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 #define BCNT_Pos (4U) -#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 */ -#define BCNT BCNT_Msk // Byte count */ +#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 +#define BCNT BCNT_Msk // Byte count #define DPID_Pos (15U) -#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 */ -#define DPID DPID_Msk // Data PID */ -#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 */ -#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 */ +#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 +#define DPID DPID_Msk // Data PID +#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 +#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 #define PKTSTS_Pos (17U) -#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 */ -#define PKTSTS PKTSTS_Msk // Packet status */ -#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 */ -#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 */ -#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 */ -#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 */ +#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 +#define PKTSTS PKTSTS_Msk // Packet status +#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 +#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 +#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 +#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 #define EPNUM_Pos (0U) -#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F */ -#define EPNUM EPNUM_Msk // Endpoint number */ -#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 */ -#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 */ -#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 */ -#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 */ +#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F +#define EPNUM EPNUM_Msk // Endpoint number +#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 +#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 +#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 +#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 #define FRMNUM_Pos (21U) -#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 */ -#define FRMNUM FRMNUM_Msk // Frame number */ -#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 */ -#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 */ -#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 */ -#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 */ +#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 +#define FRMNUM FRMNUM_Msk // Frame number +#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 +#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 +#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 +#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 #endif /******************** Bit definition for GRXFSIZ register ********************/ #define GRXFSIZ_RXFD_Pos (0U) -#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF */ -#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth */ +#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF +#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth /******************** Bit definition for DVBUSDIS register ********************/ #define DVBUSDIS_VBUSDT_Pos (0U) -#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF */ -#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time */ +#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF +#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time /******************** Bit definition for OTG register ********************/ #define GNPTXFSIZ_NPTXFSA_Pos (0U) -#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF */ -#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address */ +#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF +#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address #define GNPTXFSIZ_NPTXFD_Pos (16U) -#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 */ -#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth */ +#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 +#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth #define DIEPTXF0_TX0FSA_Pos (0U) -#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF */ -#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address */ +#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF +#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address #define DIEPTXF0_TX0FD_Pos (16U) -#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 */ -#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth */ +#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 +#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth /******************** Bit definition for DVBUSPULSE register ********************/ #define DVBUSPULSE_DVBUSP_Pos (0U) -#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF */ -#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time */ +#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF +#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time /******************** Bit definition for GNPTXSTS register ********************/ #define GNPTXSTS_NPTXFSAV_Pos (0U) -#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF */ -#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available */ +#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF +#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available #define GNPTXSTS_NPTQXSAV_Pos (16U) -#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 */ -#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available */ -#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 */ -#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 */ -#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 */ -#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 */ -#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 */ -#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 */ -#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 */ -#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 */ +#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 +#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available +#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 +#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 +#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 +#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 +#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 +#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 +#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 +#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 #define GNPTXSTS_NPTXQTOP_Pos (24U) -#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 */ -#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue */ -#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 */ -#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 */ -#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 */ -#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 */ -#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 */ -#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 */ -#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 */ +#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 +#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue +#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 +#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 +#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 +#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 +#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 +#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 +#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 /******************** Bit definition for DTHRCTL register ********************/ #define DTHRCTL_NONISOTHREN_Pos (0U) -#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 */ -#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable */ +#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 +#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable #define DTHRCTL_ISOTHREN_Pos (1U) -#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 */ -#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable */ +#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 +#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable #define DTHRCTL_TXTHRLEN_Pos (2U) -#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC */ -#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length */ -#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 */ -#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 */ -#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 */ -#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 */ -#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 */ -#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 */ -#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 */ -#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 */ -#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 */ +#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC +#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length +#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 +#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 +#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 +#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 +#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 +#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 +#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 +#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 +#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 #define DTHRCTL_RXTHREN_Pos (16U) -#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 */ -#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable */ +#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 +#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable #define DTHRCTL_RXTHRLEN_Pos (17U) -#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 */ -#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length */ -#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 */ -#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 */ -#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 */ -#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 */ -#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 */ -#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 */ -#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 */ -#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 */ -#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 */ +#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 +#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length +#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 +#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 +#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 +#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 +#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 +#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 +#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 +#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 +#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 #define DTHRCTL_ARPEN_Pos (27U) -#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 */ -#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable */ +#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 +#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable /******************** Bit definition for DIEPEMPMSK register ********************/ #define DIEPEMPMSK_INEPTXFEM_Pos (0U) -#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF */ -#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits */ +#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF +#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits /******************** Bit definition for DEACHINT register ********************/ #define DEACHINT_IEP1INT_Pos (1U) -#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 */ -#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit */ +#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 +#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit #define DEACHINT_OEP1INT_Pos (17U) -#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 */ -#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit */ +#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 +#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit /******************** Bit definition for GCCFG register ********************/ #define STM32_GCCFG_DCDET_Pos (0U) -#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 */ -#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status */ +#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 +#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status + #define STM32_GCCFG_PDET_Pos (1U) -#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 */ -#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status */ +#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 +#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status + #define STM32_GCCFG_SDET_Pos (2U) -#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 */ -#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status */ +#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 +#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status + #define STM32_GCCFG_PS2DET_Pos (3U) -#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 */ -#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status */ +#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 +#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status + #define STM32_GCCFG_PWRDWN_Pos (16U) -#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 */ -#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down */ +#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 +#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down + #define STM32_GCCFG_BCDEN_Pos (17U) -#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 */ -#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable */ +#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 +#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable + #define STM32_GCCFG_DCDEN_Pos (18U) -#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 */ +#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 #define STM32_GCCFG_DCDEN STM32_GCCFG_DCDEN_Msk // Data contact detection (DCD) mode enable*/ + #define STM32_GCCFG_PDEN_Pos (19U) -#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 */ +#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 #define STM32_GCCFG_PDEN STM32_GCCFG_PDEN_Msk // Primary detection (PD) mode enable*/ + #define STM32_GCCFG_SDEN_Pos (20U) -#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 */ -#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable */ +#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 +#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable + #define STM32_GCCFG_VBDEN_Pos (21U) -#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 */ -#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable */ +#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 +#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable + #define STM32_GCCFG_OTGIDEN_Pos (22U) -#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 */ -#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable */ +#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 +#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable + #define STM32_GCCFG_PHYHSEN_Pos (23U) -#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 */ -#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable */ +#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 +#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable + +// TODO stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above +//#define STM32_GCCFG_SDEN_Pos (22U) +//#define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000 +//#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable + +// TODO stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above +#define STM32_GCCFG_VBVALOVAL_Pos (23U) +#define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000 +#define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input + +#define STM32_GCCFG_VBVALEXTOEN_Pos (24U) +#define STM32_GCCFG_VBVALEXTOEN_Msk (0x1U << STM32_GCCFG_VBVALEXTOEN_Pos) // 0x01000000 +#define STM32_GCCFG_VBVALEXTOEN STM32_GCCFG_VBVALEXTOEN_Msk // Enables of VBUSVLDEXT0 femtoPHY input override + +#define STM32_GCCFG_PULLDOWNEN_Pos (25U) +#define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000 +#define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled + /******************** Bit definition for DEACHINTMSK register ********************/ #define DEACHINTMSK_IEP1INTM_Pos (1U) -#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 */ -#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit */ +#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 +#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit #define DEACHINTMSK_OEP1INTM_Pos (17U) -#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 */ -#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit */ +#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 +#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit /******************** Bit definition for CID register ********************/ #define CID_PRODUCT_ID_Pos (0U) -#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF */ -#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field */ +#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF +#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field /******************** Bit definition for GLPMCFG register ********************/ #define GLPMCFG_LPMEN_Pos (0U) -#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 */ -#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable */ +#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 +#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable #define GLPMCFG_LPMACK_Pos (1U) -#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 */ -#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable */ +#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 +#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable #define GLPMCFG_BESL_Pos (2U) -#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C */ -#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token */ +#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C +#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token #define GLPMCFG_REMWAKE_Pos (6U) -#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 */ -#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token */ +#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 +#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token #define GLPMCFG_L1SSEN_Pos (7U) -#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 */ -#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable */ +#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 +#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable #define GLPMCFG_BESLTHRS_Pos (8U) -#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 */ -#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold */ +#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 +#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold #define GLPMCFG_L1DSEN_Pos (12U) -#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 */ -#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable */ +#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 +#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable #define GLPMCFG_LPMRSP_Pos (13U) -#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 */ -#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response */ +#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 +#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response #define GLPMCFG_SLPSTS_Pos (15U) -#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 */ -#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status */ +#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 +#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status #define GLPMCFG_L1RSMOK_Pos (16U) -#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 */ -#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK */ +#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 +#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK #define GLPMCFG_LPMCHIDX_Pos (17U) -#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 */ -#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index */ +#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 +#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index #define GLPMCFG_LPMRCNT_Pos (21U) -#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 */ -#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count */ +#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 +#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count #define GLPMCFG_SNDLPM_Pos (24U) -#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 */ -#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction */ +#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 +#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction #define GLPMCFG_LPMRCNTSTS_Pos (25U) -#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 */ -#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status */ +#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 +#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status #define GLPMCFG_ENBESL_Pos (28U) -#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 */ -#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency */ +#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 +#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency /******************** Bit definition for DIEPEACHMSK1 register ********************/ #define DIEPEACHMSK1_XFRCM_Pos (0U) -#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ -#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 +#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask #define DIEPEACHMSK1_EPDM_Pos (1U) -#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 */ -#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 +#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask #define DIEPEACHMSK1_TOM_Pos (3U) -#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 */ -#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */ +#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 +#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) #define DIEPEACHMSK1_ITTXFEMSK_Pos (4U) -#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ -#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 +#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DIEPEACHMSK1_INEPNMM_Pos (5U) -#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ -#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 +#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask #define DIEPEACHMSK1_INEPNEM_Pos (6U) -#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ -#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 +#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask #define DIEPEACHMSK1_TXFURM_Pos (8U) -#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ -#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask */ +#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 +#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask #define DIEPEACHMSK1_BIM_Pos (9U) -#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 */ -#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 +#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask #define DIEPEACHMSK1_NAKM_Pos (13U) -#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 */ -#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ +#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 +#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask /******************** Bit definition for HPRT register ********************/ #define HPRT_PCSTS_Pos (0U) -#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 */ -#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status */ +#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 +#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status #define HPRT_PCDET_Pos (1U) -#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 */ -#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected */ +#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 +#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected #define HPRT_PENA_Pos (2U) -#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 */ -#define HPRT_PENA HPRT_PENA_Msk // Port enable */ +#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 +#define HPRT_PENA HPRT_PENA_Msk // Port enable #define HPRT_PENCHNG_Pos (3U) -#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 */ -#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change */ +#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 +#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change #define HPRT_POCA_Pos (4U) -#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 */ -#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active */ +#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 +#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active #define HPRT_POCCHNG_Pos (5U) -#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 */ -#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change */ +#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 +#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change #define HPRT_PRES_Pos (6U) -#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 */ -#define HPRT_PRES HPRT_PRES_Msk // Port resume */ +#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 +#define HPRT_PRES HPRT_PRES_Msk // Port resume #define HPRT_PSUSP_Pos (7U) -#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 */ -#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend */ +#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 +#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend #define HPRT_PRST_Pos (8U) -#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 */ -#define HPRT_PRST HPRT_PRST_Msk // Port reset */ +#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 +#define HPRT_PRST HPRT_PRST_Msk // Port reset #define HPRT_PLSTS_Pos (10U) -#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 */ -#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status */ -#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 */ -#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 */ +#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 +#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status +#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 +#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 #define HPRT_PPWR_Pos (12U) -#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 */ -#define HPRT_PPWR HPRT_PPWR_Msk // Port power */ +#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 +#define HPRT_PPWR HPRT_PPWR_Msk // Port power #define HPRT_PTCTL_Pos (13U) -#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 */ -#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control */ -#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 */ -#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 */ -#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 */ -#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 */ +#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 +#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control +#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 +#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 +#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 +#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 #define HPRT_PSPD_Pos (17U) -#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 */ -#define HPRT_PSPD HPRT_PSPD_Msk // Port speed */ -#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 */ -#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 */ +#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 +#define HPRT_PSPD HPRT_PSPD_Msk // Port speed +#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 +#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 /******************** Bit definition for DOEPEACHMSK1 register ********************/ #define DOEPEACHMSK1_XFRCM_Pos (0U) -#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 */ -#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */ +#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 +#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask #define DOEPEACHMSK1_EPDM_Pos (1U) -#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 */ -#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */ +#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 +#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask #define DOEPEACHMSK1_TOM_Pos (3U) -#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 */ -#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask */ +#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 +#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask #define DOEPEACHMSK1_ITTXFEMSK_Pos (4U) -#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */ -#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */ +#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 +#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask #define DOEPEACHMSK1_INEPNMM_Pos (5U) -#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */ -#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */ +#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 +#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask #define DOEPEACHMSK1_INEPNEM_Pos (6U) -#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */ -#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */ +#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 +#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask #define DOEPEACHMSK1_TXFURM_Pos (8U) -#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 */ -#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask */ +#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 +#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask #define DOEPEACHMSK1_BIM_Pos (9U) -#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 */ -#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask */ +#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 +#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask #define DOEPEACHMSK1_BERRM_Pos (12U) -#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 */ -#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask */ +#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 +#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask #define DOEPEACHMSK1_NAKM_Pos (13U) -#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 */ -#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask */ +#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 +#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask #define DOEPEACHMSK1_NYETM_Pos (14U) -#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 */ -#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask */ +#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 +#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask /******************** Bit definition for HPTXFSIZ register ********************/ #define HPTXFSIZ_PTXSA_Pos (0U) -#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF */ -#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address */ +#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF +#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address #define HPTXFSIZ_PTXFD_Pos (16U) -#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 */ -#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth */ +#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 +#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth /******************** Bit definition for DIEPCTL register ********************/ #define DIEPCTL_MPSIZ_Pos (0U) -#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF */ -#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size */ +#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF +#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size #define DIEPCTL_USBAEP_Pos (15U) -#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 */ -#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint */ +#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 +#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint #define DIEPCTL_EONUM_DPID_Pos (16U) -#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 */ -#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame */ +#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 +#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame #define DIEPCTL_NAKSTS_Pos (17U) -#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 */ -#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status */ +#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 +#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status #define DIEPCTL_EPTYP_Pos (18U) -#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 */ -#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type */ -#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 */ -#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 +#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type +#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 +#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 #define DIEPCTL_STALL_Pos (21U) -#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 */ -#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake */ +#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 +#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake #define DIEPCTL_TXFNUM_Pos (22U) -#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 */ -#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number */ -#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 */ -#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 */ -#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 */ -#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 */ +#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 +#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number +#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 +#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 +#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 +#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 #define DIEPCTL_CNAK_Pos (26U) -#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 */ -#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK */ +#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 +#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK #define DIEPCTL_SNAK_Pos (27U) -#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 */ -#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK */ +#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 +#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK #define DIEPCTL_SD0PID_SEVNFRM_Pos (28U) -#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ -#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 +#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID #define DIEPCTL_SODDFRM_Pos (29U) -#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 */ -#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame */ +#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 +#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame #define DIEPCTL_EPDIS_Pos (30U) -#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 */ -#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable */ +#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 +#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable #define DIEPCTL_EPENA_Pos (31U) -#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 */ -#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable */ +#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 +#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for HCCHAR register ********************/ #define HCCHAR_MPSIZ_Pos (0U) -#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF */ -#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size */ +#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF +#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size #define HCCHAR_EPNUM_Pos (11U) -#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 */ -#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number */ -#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 */ -#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 */ -#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 */ -#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 */ +#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 +#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number +#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 +#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 +#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 +#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 #define HCCHAR_EPDIR_Pos (15U) -#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 */ -#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction */ +#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 +#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction #define HCCHAR_LSDEV_Pos (17U) -#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 */ -#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device */ +#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 +#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device #define HCCHAR_EPTYP_Pos (18U) -#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 */ -#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type */ -#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 */ -#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 */ +#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 +#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type +#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 +#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 #define HCCHAR_MC_Pos (20U) -#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 */ -#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) */ -#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 */ -#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 */ +#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 +#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) +#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 +#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 #define HCCHAR_DAD_Pos (22U) -#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 */ -#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address */ -#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 */ -#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 */ -#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 */ -#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 */ -#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 */ -#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 */ -#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 */ +#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 +#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address +#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 +#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 +#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 +#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 +#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 +#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 +#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 #define HCCHAR_ODDFRM_Pos (29U) -#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 */ -#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame */ +#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 +#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame #define HCCHAR_CHDIS_Pos (30U) -#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 */ -#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable */ +#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 +#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable #define HCCHAR_CHENA_Pos (31U) -#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 */ -#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable */ +#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 +#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable /******************** Bit definition for HCSPLT register ********************/ #define HCSPLT_PRTADDR_Pos (0U) -#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F */ -#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address */ -#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 */ -#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 */ -#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 */ -#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 */ -#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 */ -#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 */ -#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 */ +#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F +#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address +#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 +#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 +#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 +#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 +#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 +#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 +#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 #define HCSPLT_HUBADDR_Pos (7U) -#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 */ -#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address */ -#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 */ -#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 */ -#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 */ -#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 */ -#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 */ -#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 */ -#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 */ +#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 +#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address +#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 +#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 +#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 +#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 +#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 +#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 +#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 #define HCSPLT_XACTPOS_Pos (14U) -#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 */ -#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS */ -#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 */ -#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 */ +#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 +#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS +#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 +#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 #define HCSPLT_COMPLSPLT_Pos (16U) -#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 */ -#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split */ +#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 +#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split #define HCSPLT_SPLITEN_Pos (31U) -#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 */ -#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable */ +#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 +#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable /******************** Bit definition for HCINT register ********************/ #define HCINT_XFRC_Pos (0U) -#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 */ -#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed */ +#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 +#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed #define HCINT_CHH_Pos (1U) -#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 */ -#define HCINT_CHH HCINT_CHH_Msk // Channel halted */ +#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 +#define HCINT_CHH HCINT_CHH_Msk // Channel halted #define HCINT_AHBERR_Pos (2U) -#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 */ -#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error */ +#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 +#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error #define HCINT_STALL_Pos (3U) -#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 */ -#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt */ +#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 +#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt #define HCINT_NAK_Pos (4U) -#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 */ -#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt */ +#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 +#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt #define HCINT_ACK_Pos (5U) -#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 */ -#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt */ +#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 +#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt #define HCINT_NYET_Pos (6U) -#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 */ -#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt */ +#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 +#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt #define HCINT_TXERR_Pos (7U) -#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 */ -#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error */ +#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 +#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error #define HCINT_BBERR_Pos (8U) -#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 */ -#define HCINT_BBERR HCINT_BBERR_Msk // Babble error */ +#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 +#define HCINT_BBERR HCINT_BBERR_Msk // Babble error #define HCINT_FRMOR_Pos (9U) -#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 */ -#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun */ +#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 +#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun #define HCINT_DTERR_Pos (10U) -#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 */ -#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error */ +#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 +#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error /******************** Bit definition for DIEPINT register ********************/ #define DIEPINT_XFRC_Pos (0U) -#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 */ -#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 +#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt #define DIEPINT_EPDISD_Pos (1U) -#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 */ -#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 +#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt #define DIEPINT_AHBERR_Pos (2U) -#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 */ -#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction */ +#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 +#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction #define DIEPINT_TOC_Pos (3U) -#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 */ -#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition */ +#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 +#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition #define DIEPINT_ITTXFE_Pos (4U) -#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 */ -#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty */ +#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 +#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty #define DIEPINT_INEPNM_Pos (5U) -#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 */ -#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch */ +#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 +#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch #define DIEPINT_INEPNE_Pos (6U) -#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 */ -#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective */ +#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 +#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective #define DIEPINT_TXFE_Pos (7U) -#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 */ -#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty */ +#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 +#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty #define DIEPINT_TXFIFOUDRN_Pos (8U) -#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 */ -#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun */ +#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 +#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun #define DIEPINT_BNA_Pos (9U) -#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 */ -#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt */ +#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 +#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt #define DIEPINT_PKTDRPSTS_Pos (11U) -#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 */ -#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status */ +#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 +#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status #define DIEPINT_BERR_Pos (12U) -#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 */ -#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt */ +#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 +#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt #define DIEPINT_NAK_Pos (13U) -#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 */ -#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt */ +#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 +#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt /******************** Bit definition for HCINTMSK register ********************/ #define HCINTMSK_XFRCM_Pos (0U) -#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 */ -#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask */ +#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 +#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask #define HCINTMSK_CHHM_Pos (1U) -#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 */ -#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask */ +#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 +#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask #define HCINTMSK_AHBERR_Pos (2U) -#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 */ -#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error */ +#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 +#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error #define HCINTMSK_STALLM_Pos (3U) -#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 */ -#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask */ +#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 +#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask #define HCINTMSK_NAKM_Pos (4U) -#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 */ -#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask */ +#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 +#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask #define HCINTMSK_ACKM_Pos (5U) -#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 */ -#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask */ +#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 +#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask #define HCINTMSK_NYET_Pos (6U) -#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 */ -#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask */ +#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 +#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask #define HCINTMSK_TXERRM_Pos (7U) -#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 */ -#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask */ +#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 +#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask #define HCINTMSK_BBERRM_Pos (8U) -#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 */ -#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask */ +#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 +#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask #define HCINTMSK_FRMORM_Pos (9U) -#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 */ -#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask */ +#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 +#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask #define HCINTMSK_DTERRM_Pos (10U) -#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 */ -#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask */ +#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 +#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask /******************** Bit definition for DIEPTSIZ register ********************/ #define DIEPTSIZ_XFRSIZ_Pos (0U) -#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size #define DIEPTSIZ_PKTCNT_Pos (19U) -#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count */ +#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count #define DIEPTSIZ_MULCNT_Pos (29U) -#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 */ -#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count */ +#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 +#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count /******************** Bit definition for HCTSIZ register ********************/ #define HCTSIZ_XFRSIZ_Pos (0U) -#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size */ +#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size #define HCTSIZ_PKTCNT_Pos (19U) -#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count */ +#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count #define HCTSIZ_DOPING_Pos (31U) -#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 */ -#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING */ +#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 +#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING #define HCTSIZ_DPID_Pos (29U) -#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 */ -#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID */ -#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 */ -#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 */ +#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 +#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID +#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 +#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 /******************** Bit definition for DIEPDMA register ********************/ #define DIEPDMA_DMAADDR_Pos (0U) -#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF */ -#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address */ +#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF +#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address /******************** Bit definition for HCDMA register ********************/ #define HCDMA_DMAADDR_Pos (0U) -#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF */ -#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address */ +#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF +#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address /******************** Bit definition for DTXFSTS register ********************/ #define DTXFSTS_INEPTFSAV_Pos (0U) -#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF */ -#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available */ +#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF +#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available /******************** Bit definition for DIEPTXF register ********************/ #define DIEPTXF_INEPTXSA_Pos (0U) -#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF */ -#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address */ +#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF +#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address #define DIEPTXF_INEPTXFD_Pos (16U) -#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 */ -#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth */ +#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 +#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth /******************** Bit definition for DOEPCTL register ********************/ #define DOEPCTL_MPSIZ_Pos (0U) -#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF */ -#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size */ //Bit 1 */ +#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF +#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size //Bit 1 #define DOEPCTL_USBAEP_Pos (15U) -#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 */ -#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint */ +#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 +#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint #define DOEPCTL_NAKSTS_Pos (17U) -#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 */ -#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status */ +#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 +#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status #define DOEPCTL_SD0PID_SEVNFRM_Pos (28U) -#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */ -#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */ +#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 +#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID #define DOEPCTL_SODDFRM_Pos (29U) -#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 */ -#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame */ +#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 +#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame #define DOEPCTL_EPTYP_Pos (18U) -#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 */ -#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type */ -#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 */ -#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 */ +#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 +#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type +#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 +#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 #define DOEPCTL_SNPM_Pos (20U) -#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 */ -#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode */ +#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 +#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode #define DOEPCTL_STALL_Pos (21U) -#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 */ -#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake */ +#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 +#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake #define DOEPCTL_CNAK_Pos (26U) -#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 */ -#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK */ +#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 +#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK #define DOEPCTL_SNAK_Pos (27U) -#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 */ -#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK */ +#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 +#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK #define DOEPCTL_EPDIS_Pos (30U) -#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 */ -#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable */ +#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 +#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable #define DOEPCTL_EPENA_Pos (31U) -#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 */ -#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable */ +#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 +#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for DOEPINT register ********************/ #define DOEPINT_XFRC_Pos (0U) -#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 */ -#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt */ +#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 +#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt #define DOEPINT_EPDISD_Pos (1U) -#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 */ -#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt */ +#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 +#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt #define DOEPINT_AHBERR_Pos (2U) -#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 */ -#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction */ +#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 +#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction #define DOEPINT_STUP_Pos (3U) -#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 */ -#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done */ +#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 +#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done #define DOEPINT_OTEPDIS_Pos (4U) -#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 */ -#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled */ +#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 +#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled #define DOEPINT_OTEPSPR_Pos (5U) -#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 */ -#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write */ +#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 +#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write #define DOEPINT_B2BSTUP_Pos (6U) -#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 */ -#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received */ +#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 +#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received #define DOEPINT_OUTPKTERR_Pos (8U) -#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 */ -#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error */ +#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 +#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error #define DOEPINT_NAK_Pos (13U) -#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 */ -#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device */ +#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 +#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device #define DOEPINT_NYET_Pos (14U) -#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 */ -#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt */ +#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 +#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt #define DOEPINT_STPKTRX_Pos (15U) -#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 */ -#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received */ +#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 +#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received /******************** Bit definition for DOEPTSIZ register ********************/ #define DOEPTSIZ_XFRSIZ_Pos (0U) -#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */ -#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size */ +#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF +#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size #define DOEPTSIZ_PKTCNT_Pos (19U) -#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */ -#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count */ +#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 +#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count #define DOEPTSIZ_STUPCNT_Pos (29U) -#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 */ -#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count */ -#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 */ -#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 */ +#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 +#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count +#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 +#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 /******************** Bit definition for PCGCTL register ********************/ #define PCGCTL_IF_DEV_MODE TU_BIT(31) diff --git a/test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_xmc.h b/test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_xmc.h similarity index 100% rename from test-devices/loopback-stm32/lib/tinyusb/dwc2/dwc2_xmc.h rename to test-devices/loopback-stm32/lib/tinyusb/portable/synopsys/dwc2/dwc2_xmc.h diff --git a/test-devices/loopback-stm32/lib/tinyusb/tusb.c b/test-devices/loopback-stm32/lib/tinyusb/tusb.c index 85fe5a3c..0092267a 100644 --- a/test-devices/loopback-stm32/lib/tinyusb/tusb.c +++ b/test-devices/loopback-stm32/lib/tinyusb/tusb.c @@ -36,39 +36,37 @@ #endif #if CFG_TUH_ENABLED -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #endif //--------------------------------------------------------------------+ // Public API //--------------------------------------------------------------------+ -bool tusb_init(void) -{ -#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) +bool tusb_init(void) { + #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) // init device stack CFG_TUSB_RHPORTx_MODE must be defined TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); -#endif + #endif -#if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT) + #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT) // init host stack CFG_TUSB_RHPORTx_MODE must be defined TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); -#endif + #endif return true; } -bool tusb_inited(void) -{ +bool tusb_inited(void) { bool ret = false; -#if CFG_TUD_ENABLED + #if CFG_TUD_ENABLED ret = ret || tud_inited(); -#endif + #endif -#if CFG_TUH_ENABLED + #if CFG_TUH_ENABLED ret = ret || tuh_inited(); -#endif + #endif return ret; } @@ -77,43 +75,35 @@ bool tusb_inited(void) // Descriptor helper //--------------------------------------------------------------------+ -uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) -{ - while(desc+1 < end) - { - if ( desc[1] == byte1 ) return desc; +uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) { + while (desc + 1 < end) { + if (desc[1] == byte1) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } -uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) -{ - while(desc+2 < end) - { - if ( desc[1] == byte1 && desc[2] == byte2) return desc; +uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) { + while (desc + 2 < end) { + if (desc[1] == byte1 && desc[2] == byte2) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } -uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) -{ - while(desc+3 < end) - { +uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) { + while (desc + 3 < end) { if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc; desc += desc[DESC_OFFSET_LEN]; } return NULL; } - //--------------------------------------------------------------------+ // Endpoint Helper for both Host and Device stack //--------------------------------------------------------------------+ -bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) -{ +bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; // pre-check to help reducing mutex lock @@ -122,111 +112,93 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) // can only claim the endpoint if it is not busy and not claimed yet. bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0); - if (available) - { + if (available) { ep_state->claimed = 1; } (void) osal_mutex_unlock(mutex); - return available; } -bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) -{ +bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; - (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only release the endpoint if it is claimed and not busy bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0); - if (ret) - { + if (ret) { ep_state->claimed = 0; } (void) osal_mutex_unlock(mutex); - return ret; } -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) -{ +bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { + switch (desc_ep->bmAttributes.xfer) { + case TUSB_XFER_ISOCHRONOUS: { uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); TU_ASSERT(max_packet_size <= spec_size); + break; } - break; case TUSB_XFER_BULK: - if (speed == TUSB_SPEED_HIGH) - { + if (speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 TU_ASSERT(max_packet_size == 512); - }else - { + } else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 TU_ASSERT(max_packet_size <= 64); } - break; + break; - case TUSB_XFER_INTERRUPT: - { + case TUSB_XFER_INTERRUPT: { uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); TU_ASSERT(max_packet_size <= spec_size); + break; } - break; - default: return false; + default: + return false; } return true; } -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) -{ +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, + uint8_t driver_id) { uint8_t const* p_desc = (uint8_t const*) desc_itf; uint8_t const* desc_end = p_desc + desc_len; - while( p_desc < desc_end ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { + while (p_desc < desc_end) { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - p_desc = tu_desc_next(p_desc); } } -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) { uint8_t const* p_desc = (uint8_t const*) desc_itf; uint16_t len = 0; - while (itf_count--) - { + while (itf_count--) { // Next on interface desc len += tu_desc_len(desc_itf); p_desc = tu_desc_next(p_desc); - while (len < max_len) - { + while (len < max_len) { // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) - { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { + return len; + } + if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0) { break; } @@ -243,9 +215,8 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, //--------------------------------------------------------------------+ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, - void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) -{ - osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex); + void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) { + osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef); (void) new_mutex; (void) is_tx; @@ -259,92 +230,82 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } +bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { + (void) s; + #if OSAL_MUTEX_REQUIRED + if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr); + if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd); + #endif + return true; +} + TU_ATTR_ALWAYS_INLINE static inline -bool stream_claim(tu_edpt_stream_t* s) -{ - if (s->is_host) - { +bool stream_claim(tu_edpt_stream_t* s) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_claim(s->daddr, s->ep_addr); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_claim(s->rhport, s->ep_addr); #endif } - return false; } TU_ATTR_ALWAYS_INLINE static inline -bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) -{ - if (s->is_host) - { +bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_xfer(s->daddr, s->ep_addr, count ? s->ep_buf : NULL, count); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_xfer(s->rhport, s->ep_addr, count ? s->ep_buf : NULL, count); #endif } - return false; } TU_ATTR_ALWAYS_INLINE static inline -bool stream_release(tu_edpt_stream_t* s) -{ - if (s->is_host) - { +bool stream_release(tu_edpt_stream_t* s) { + if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_release(s->daddr, s->ep_addr); #endif - }else - { + } else { #if CFG_TUD_ENABLED return usbd_edpt_release(s->rhport, s->ep_addr); #endif } - return false; } //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ - -bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) -{ +bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size - TU_VERIFY( !tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize-1))) ); - - TU_VERIFY( stream_claim(s) ); - TU_ASSERT( stream_xfer(s, 0) ); - + TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize - 1)))); + TU_VERIFY(stream_claim(s)); + TU_ASSERT(stream_xfer(s, 0)); return true; } -uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) { // skip if no data - TU_VERIFY( tu_fifo_count(&s->ff), 0 ); + TU_VERIFY(tu_fifo_count(&s->ff), 0); // Claim the endpoint - TU_VERIFY( stream_claim(s), 0 ); + TU_VERIFY(stream_claim(s), 0); // Pull data from FIFO -> EP buf uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); - if ( count ) - { - TU_ASSERT( stream_xfer(s, count), 0 ); + if (count) { + TU_ASSERT(stream_xfer(s, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer // Note: data is dropped if terminal is not connected stream_release(s); @@ -352,16 +313,13 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) } } -uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize) -{ +uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) { TU_VERIFY(bufsize); // TODO support ZLP - uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); // flush if fifo has more than packet size or // in rare case: fifo depth is configured too small (which never reach packet size) - if ( (tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize) ) - { + if ((tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize)) { tu_edpt_stream_write_xfer(s); } @@ -371,9 +329,7 @@ uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ - -uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) { uint16_t available = tu_fifo_remaining(&s->ff); // Prepare for incoming data but only allow what we can store in the ring buffer. @@ -388,25 +344,21 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) // get available again since fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&s->ff); - if ( available >= s->ep_packetsize ) - { + if (available >= s->ep_packetsize) { // multiple of packet size limit by ep bufsize - uint16_t count = (uint16_t) (available & ~(s->ep_packetsize -1)); + uint16_t count = (uint16_t) (available & ~(s->ep_packetsize - 1)); count = tu_min16(count, s->ep_bufsize); - TU_ASSERT( stream_xfer(s, count), 0 ); - + TU_ASSERT(stream_xfer(s, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer stream_release(s); return 0; } } -uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) -{ +uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); tu_edpt_stream_read_xfer(s); return num_read; @@ -419,39 +371,36 @@ uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize #if CFG_TUSB_DEBUG #include -#if CFG_TUSB_DEBUG >= 2 - -char const* const tu_str_speed[] = { "Full", "Low", "High" }; -char const* const tu_str_std_request[] = -{ - "Get Status" , - "Clear Feature" , - "Reserved" , - "Set Feature" , - "Reserved" , - "Set Address" , - "Get Descriptor" , - "Set Descriptor" , - "Get Configuration" , - "Set Configuration" , - "Get Interface" , - "Set Interface" , - "Synch Frame" +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL +char const* const tu_str_speed[] = {"Full", "Low", "High"}; +char const* const tu_str_std_request[] = { + "Get Status", + "Clear Feature", + "Reserved", + "Set Feature", + "Reserved", + "Set Address", + "Get Descriptor", + "Set Descriptor", + "Get Configuration", + "Set Configuration", + "Get Interface", + "Set Interface", + "Synch Frame" }; +char const* const tu_str_xfer_result[] = { + "OK", "FAILED", "STALLED", "TIMEOUT" +}; #endif -static void dump_str_line(uint8_t const* buf, uint16_t count) -{ +static void dump_str_line(uint8_t const* buf, uint16_t count) { tu_printf(" |"); - // each line is 16 bytes - for(uint16_t i=0; i= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x @@ -119,7 +132,9 @@ // NXP Kinetis #define OPT_MCU_KINETIS_KL 1200 ///< NXP KL series -#define OPT_MCU_KINETIS_K32 1201 ///< NXP K32 series +#define OPT_MCU_KINETIS_K32L 1201 ///< NXP K32L series +#define OPT_MCU_KINETIS_K32 1201 ///< Alias to K32L +#define OPT_MCU_KINETIS_K 1202 ///< NXP K series #define OPT_MCU_MKL25ZXX 1200 ///< Alias to KL (obsolete) #define OPT_MCU_K32L2BXX 1201 ///< Alias to K32 (obsolete) @@ -133,7 +148,6 @@ #define OPT_MCU_RX72N 1402 ///< Renesas RX72N #define OPT_MCU_RAXXX 1403 ///< Renesas RAxxx families - // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 @@ -165,11 +179,17 @@ // WCH #define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 +#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x + -// Helper to check if configured MCU is one of listed +// NXP LPC MCX +#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series +#define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series + +// Check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input -#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) -#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) +#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) +#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) //--------------------------------------------------------------------+ // Supported OS @@ -274,7 +294,7 @@ // In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler // to generate unaligned access code. // LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM -#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) +#if TUD_OPT_HIGH_SPEED && TU_CHECK_MCU(OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX) #define TUP_MCU_STRICT_ALIGN 1 #else #define TUP_MCU_STRICT_ALIGN 0 @@ -290,15 +310,24 @@ #define CFG_TUSB_DEBUG 0 #endif -// TODO MEM_SECTION can be different for host and device controller -// should use CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION +// Level where CFG_TUSB_DEBUG must be at least for USBH is logged +#ifndef CFG_TUH_LOG_LEVEL + #define CFG_TUH_LOG_LEVEL 2 +#endif + +// Level where CFG_TUSB_DEBUG must be at least for USBD is logged +#ifndef CFG_TUD_LOG_LEVEL + #define CFG_TUD_LOG_LEVEL 2 +#endif + +// Memory section for placing buffer used for usb transferring. If MEM_SECTION is different for +// host and device use: CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION instead #ifndef CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_SECTION #endif -// alignment requirement of buffer used for endpoint transferring -// TODO MEM_ALIGN can be different for host and device controller -// should use CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN +// Alignment requirement of buffer used for usb transferring. if MEM_ALIGN is different for +// host and device controller use: CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN instead #ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif @@ -316,24 +345,14 @@ // Device Options (Default) //-------------------------------------------------------------------- -// Attribute to place data in accessible RAM for device controller -// default to CFG_TUSB_MEM_SECTION for backward-compatible +// Attribute to place data in accessible RAM for device controller (default: CFG_TUSB_MEM_SECTION) #ifndef CFG_TUD_MEM_SECTION - #ifdef CFG_TUSB_MEM_SECTION - #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION - #else - #define CFG_TUD_MEM_SECTION - #endif + #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION #endif -// Attribute to align memory for device controller -// default to CFG_TUSB_MEM_ALIGN for backward-compatible +// Attribute to align memory for device controller (default: CFG_TUSB_MEM_ALIGN) #ifndef CFG_TUD_MEM_ALIGN - #ifdef CFG_TUSB_MEM_ALIGN - #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN - #else - #define CFG_TUD_MEM_ALIGN TU_ATTR_ALIGNED(4) - #endif + #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN #endif #ifndef CFG_TUD_ENDPOINT0_SIZE @@ -344,6 +363,15 @@ #define CFG_TUD_INTERFACE_MAX 16 #endif +//------------- Device Class Driver -------------// +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + +#if CFG_TUD_BTH && !defined(CFG_TUD_BTH_ISO_ALT_COUNT) +#error CFG_TUD_BTH_ISO_ALT_COUNT must be defined to tell Bluetooth driver the number of ISO endpoints to use +#endif + #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif @@ -384,10 +412,6 @@ #define CFG_TUD_DFU 0 #endif -#ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 -#endif - #ifndef CFG_TUD_ECM_RNDIS #ifdef CFG_TUD_NET #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" @@ -414,29 +438,24 @@ #endif #endif // CFG_TUH_ENABLED -// Attribute to place data in accessible RAM for host controller -// default to CFG_TUSB_MEM_SECTION for backward-compatible +// Attribute to place data in accessible RAM for host controller (default: CFG_TUSB_MEM_SECTION) #ifndef CFG_TUH_MEM_SECTION - #ifdef CFG_TUSB_MEM_SECTION - #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION - #else - #define CFG_TUH_MEM_SECTION - #endif + #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION #endif // Attribute to align memory for host controller #ifndef CFG_TUH_MEM_ALIGN - #define CFG_TUH_MEM_ALIGN TU_ATTR_ALIGNED(4) + #define CFG_TUH_MEM_ALIGN CFG_TUSB_MEM_ALIGN #endif //------------- CLASS -------------// #ifndef CFG_TUH_HUB -#define CFG_TUH_HUB 0 + #define CFG_TUH_HUB 0 #endif #ifndef CFG_TUH_CDC -#define CFG_TUH_CDC 0 + #define CFG_TUH_CDC 0 #endif #ifndef CFG_TUH_CDC_FTDI @@ -444,40 +463,85 @@ #define CFG_TUH_CDC_FTDI 0 #endif +#ifndef CFG_TUH_CDC_FTDI_VID_PID_LIST + // List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID + #define CFG_TUH_CDC_FTDI_VID_PID_LIST \ + {0x0403, 0x6001}, {0x0403, 0x6006}, {0x0403, 0x6010}, {0x0403, 0x6011}, \ + {0x0403, 0x6014}, {0x0403, 0x6015}, {0x0403, 0x8372}, {0x0403, 0xFBFA}, \ + {0x0403, 0xCD18} +#endif + #ifndef CFG_TUH_CDC_CP210X // CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 0 #endif +#ifndef CFG_TUH_CDC_CP210X_VID_PID_LIST + // List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID + #define CFG_TUH_CDC_CP210X_VID_PID_LIST \ + {0x10C4, 0xEA60}, {0x10C4, 0xEA70} +#endif + +#ifndef CFG_TUH_CDC_CH34X + // CH34X is not part of CDC class, only to re-use CDC driver API + #define CFG_TUH_CDC_CH34X 0 +#endif + +#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST + // List of product IDs that can use the CH34X CDC driver + #define CFG_TUH_CDC_CH34X_VID_PID_LIST \ + { 0x1a86, 0x5523 }, /* ch341 chip */ \ + { 0x1a86, 0x7522 }, /* ch340k chip */ \ + { 0x1a86, 0x7523 }, /* ch340 chip */ \ + { 0x1a86, 0xe523 }, /* ch330 chip */ \ + { 0x4348, 0x5523 }, /* ch340 custom chip */ \ + { 0x2184, 0x0057 }, /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ \ + { 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ +#endif + #ifndef CFG_TUH_HID -#define CFG_TUH_HID 0 + #define CFG_TUH_HID 0 #endif #ifndef CFG_TUH_MIDI -#define CFG_TUH_MIDI 0 + #define CFG_TUH_MIDI 0 #endif #ifndef CFG_TUH_MSC -#define CFG_TUH_MSC 0 + #define CFG_TUH_MSC 0 #endif #ifndef CFG_TUH_VENDOR -#define CFG_TUH_VENDOR 0 + #define CFG_TUH_VENDOR 0 #endif #ifndef CFG_TUH_API_EDPT_XFER -#define CFG_TUH_API_EDPT_XFER 0 + #define CFG_TUH_API_EDPT_XFER 0 #endif // Enable PIO-USB software host controller #ifndef CFG_TUH_RPI_PIO_USB -#define CFG_TUH_RPI_PIO_USB 0 + #define CFG_TUH_RPI_PIO_USB 0 #endif #ifndef CFG_TUD_RPI_PIO_USB -#define CFG_TUD_RPI_PIO_USB 0 + #define CFG_TUD_RPI_PIO_USB 0 #endif +// MAX3421 Host controller option +#ifndef CFG_TUH_MAX3421 + #define CFG_TUH_MAX3421 0 +#endif + +//--------------------------------------------------------------------+ +// TypeC Options (Default) +//--------------------------------------------------------------------+ + +#ifndef CFG_TUC_ENABLED +#define CFG_TUC_ENABLED 0 + +#define tuc_int_handler(_p) +#endif //------------------------------------------------------------------ // Configuration Validation diff --git a/test-devices/loopback-stm32/src/board.h b/test-devices/loopback-stm32/src/board.h index 4e032fd4..8d073409 100644 --- a/test-devices/loopback-stm32/src/board.h +++ b/test-devices/loopback-stm32/src/board.h @@ -28,6 +28,9 @@ void board_led_write(bool on); // Return the number of milliseconds since a time in the past uint32_t board_millis(void); +// Enter sleep or stop mode and wake up on USB resume +void board_sleep(void); + // USB serial number extern char board_serial_num[13]; diff --git a/test-devices/loopback-stm32/src/board_f1.c b/test-devices/loopback-stm32/src/board_f1.c index ac547f68..d0690d88 100644 --- a/test-devices/loopback-stm32/src/board_f1.c +++ b/test-devices/loopback-stm32/src/board_f1.c @@ -15,6 +15,8 @@ #include "stm32f1xx.h" #include "device/usbd.h" +#define EXTI_USBWakeUp_Line EXTI_IMR_IM18 + extern uint32_t SystemCoreClock; void SystemCoreClockUpdate(void); @@ -180,6 +182,12 @@ void board_init(void) { gpio_set_mode(GPIOB, 12, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSH_PULL); usb_init_serial_num(); + + // Wake up event is only available as interrupt, not as an event. + // See product errata sheet + set_reg(&EXTI->RTSR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line); + set_reg(&EXTI->IMR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line); + NVIC_EnableIRQ(USBWakeUp_IRQn); } uint32_t board_millis(void) { @@ -188,9 +196,38 @@ uint32_t board_millis(void) { void board_led_write(bool on) { if (on) - gpio_set(GPIOB, 12); - else gpio_clear(GPIOB, 12); + else + gpio_set(GPIOB, 12); +} + +void board_sleep(void) { + + // turn off LED + board_led_write(false); + + // pause systick interrupts + set_reg(&SysTick->CTRL, 0, SysTick_CTRL_TICKINT_Msk); + + // enter Stop mode when the CPU enters deep sleep + set_reg(&PWR->CR, 0, PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk); + + set_reg(&SCB->SCR, SCB_SCR_SLEEPDEEP_Msk, SCB_SCR_SLEEPDEEP_Msk); + + // sleep until an interrupt occurs + __WFI(); + + // reset SLEEPDEEP bit + set_reg(&SCB->SCR, 0, SCB_SCR_SLEEPDEEP_Msk); + + // after wakeup, re-enable PLL as clock source + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + // resume systick interrupts + set_reg(&SysTick->CTRL, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_TICKINT_Msk); + + // turn on LED + board_led_write(true); } @@ -201,7 +238,8 @@ void SysTick_Handler (void) { } void USBWakeUp_IRQHandler(void) { - tud_int_handler(0); + // clear interrupt + EXTI->PR = EXTI_USBWakeUp_Line; } void USB_HP_IRQHandler(void) { diff --git a/test-devices/loopback-stm32/src/board_f4.c b/test-devices/loopback-stm32/src/board_f4.c index 4499e8c9..dfb887e7 100644 --- a/test-devices/loopback-stm32/src/board_f4.c +++ b/test-devices/loopback-stm32/src/board_f4.c @@ -15,6 +15,9 @@ #include "stm32f4xx.h" #include "device/usbd.h" +#define EXTI_USBWakeUp_Line EXTI_IMR_IM18 + + extern uint32_t SystemCoreClock; void SystemCoreClockUpdate(void); @@ -85,6 +88,11 @@ const rcc_clock_setup_t clock_setup_hse_value_out_84mhz_3v3 = { #define GPIO_OSPEED_HIGH 3 +// --- additional USB register +#define PCGCCTL ((volatile uint32_t *)((uint32_t)USB_OTG_FS + USB_OTG_PCGCCTL_BASE)) + + + static inline void rcc_wait_for_osc_ready(uint32_t rcc_cr_clk_rdy) { while (get_reg(&RCC->CR, rcc_cr_clk_rdy) == 0) ; @@ -254,6 +262,13 @@ void board_init(void) { gpio_mode_setup(GPIOC, 13, GPIO_MODE_OUTPUT, GPIO_PUPD_NO_PULL); usb_init_serial_num(); + + // enable USB wakeup interrupt + EXTI->PR = EXTI_USBWakeUp_Line; + EXTI->RTSR |= EXTI_USBWakeUp_Line; + EXTI->IMR |= EXTI_USBWakeUp_Line; + NVIC_SetPriority(OTG_FS_WKUP_IRQn, 0); + NVIC_EnableIRQ(OTG_FS_WKUP_IRQn); } uint32_t board_millis(void) { @@ -262,9 +277,44 @@ uint32_t board_millis(void) { void board_led_write(bool on) { if (on) - gpio_set(GPIOC, 13); - else gpio_clear(GPIOC, 13); + else + gpio_set(GPIOC, 13); +} + +void board_sleep(void) { + + // turn off LED + board_led_write(false); + + // stop PCLK to USB + set_reg(PCGCCTL, USB_OTG_PCGCCTL_STOPCLK, USB_OTG_PCGCCTL_STOPCLK_Msk); + + // pause systick interrupts + set_reg(&SysTick->CTRL, 0, SysTick_CTRL_TICKINT_Msk); + + // enter stop mode when the CPU enters deep sleep + set_reg(&PWR->CR, 0, PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk); + + // use deep sleep mode + set_reg(&SCB->SCR, SCB_SCR_SLEEPDEEP_Msk, SCB_SCR_SLEEPDEEP_Msk); + + __WFI(); + + // reset to regular sleep mode + set_reg(&SCB->SCR, 0, SCB_SCR_SLEEPDEEP_Msk); + + // after wakeup, re-enable PLL as clock source + rcc_clock_setup_pll(&clock_setup_hse_value_out_84mhz_3v3); + + // resume systick interrupts + set_reg(&SysTick->CTRL, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_TICKINT_Msk); + + // restart PCLK to USB + set_reg(PCGCCTL, 0, USB_OTG_PCGCCTL_STOPCLK_Msk); + + // turn on LED + board_led_write(true); } @@ -278,4 +328,9 @@ void OTG_FS_IRQHandler(void) { tud_int_handler(0); } +void OTG_FS_WKUP_IRQHandler(void) { + // clear interrupt + EXTI->PR = EXTI_USBWakeUp_Line; +} + #endif diff --git a/test-devices/loopback-stm32/src/board_f7.c b/test-devices/loopback-stm32/src/board_f7.c index bdff30b4..34d40bf5 100644 --- a/test-devices/loopback-stm32/src/board_f7.c +++ b/test-devices/loopback-stm32/src/board_f7.c @@ -284,6 +284,10 @@ void board_init(void) { usb_init_serial_num(); } +void board_sleep(void) { + // not implemented yet +} + uint32_t board_millis(void) { return millis_count; } diff --git a/test-devices/loopback-stm32/src/main.c b/test-devices/loopback-stm32/src/main.c index b58c45f1..d826197e 100644 --- a/test-devices/loopback-stm32/src/main.c +++ b/test-devices/loopback-stm32/src/main.c @@ -27,6 +27,7 @@ // FIFO buffer for loopback data tu_fifo_t loopback_fifo; uint8_t loopback_buffer[BUFFER_SIZE] __attribute__ ((aligned(4))); +bool delay_loopback_reset = false; uint16_t bulk_packet_size = 64; const int num_rx_packets = 2; @@ -38,15 +39,16 @@ int echo_buffer_len; int num_echos; -// Blink durations -enum { - BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, -}; +static bool is_blinking = true; +static uint32_t led_on_until = 0; +static uint32_t blink_toogle_at = 0; +static bool is_blink_on = true; -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +static inline bool has_expired(uint32_t deadline, uint32_t now) { + return (int32_t)(now - deadline) >= 0; +} +static void led_busy(void); static void led_blinking_task(void); static void loopback_init(void); static void loopback_check_rx(void); @@ -73,7 +75,12 @@ int main(void) { // reset device in predictable state void reset_buffers(void) { - tu_fifo_clear(&loopback_fifo); + if (cust_vendor_is_transmitting(EP_LOOPBACK_TX)) { + delay_loopback_reset = true; + } else { + tu_fifo_clear(&loopback_fifo); + } + num_echos = 0; } @@ -86,6 +93,11 @@ void loopback_init(void) { // Check if the next transmission should be started void loopback_check_tx(void) { + if (delay_loopback_reset) { + tu_fifo_clear(&loopback_fifo); + delay_loopback_reset = false; + } + uint16_t n = tu_fifo_count(&loopback_fifo); if (n > 0 && !cust_vendor_is_transmitting(EP_LOOPBACK_TX)) { @@ -94,6 +106,7 @@ void loopback_check_tx(void) { n = max_size; cust_vendor_start_transmit_fifo(EP_LOOPBACK_TX, &loopback_fifo, n); + led_busy(); } } @@ -111,6 +124,7 @@ void loopback_check_rx(void) { void echo_update_state(void) { if (num_echos > 0) { cust_vendor_start_transmit(EP_ECHO_TX, echo_buffer, echo_buffer_len); + led_busy(); } else { cust_vendor_prepare_recv(EP_ECHO_RX, echo_buffer, sizeof(echo_buffer)); } @@ -130,6 +144,7 @@ void cust_vendor_rx_cb(uint8_t ep_addr, uint32_t recv_bytes) { echo_buffer_len = recv_bytes; echo_update_state(); } + led_busy(); } // Invoked when last tx transfer finished @@ -139,9 +154,12 @@ void cust_vendor_tx_cb(uint8_t ep_addr, uint32_t sent_bytes) { loopback_check_rx(); // check ZLP - if ((sent_bytes & (bulk_packet_size - 1)) == 0 - && !cust_vendor_is_transmitting(ep_addr)) + if (sent_bytes > 0 + && (sent_bytes & (bulk_packet_size - 1)) == 0 + && !cust_vendor_is_transmitting(ep_addr)) { cust_vendor_start_transmit(EP_LOOPBACK_TX, NULL, 0); + led_busy(); + } } else if (ep_addr == EP_ECHO_TX) { num_echos--; @@ -154,6 +172,7 @@ void cust_vendor_intf_open_cb(uint8_t intf) { bulk_packet_size = cust_vendor_packet_size(EP_LOOPBACK_RX); loopback_check_rx(); echo_update_state(); + led_busy(); } // Invoked when an alternate interface has been selected @@ -163,6 +182,7 @@ void cust_vendor_alt_intf_selected_cb(uint8_t intf, uint8_t alt) { loopback_check_rx(); if (alt == 0) echo_update_state(); + led_busy(); } void cust_vendor_halt_cleared_cb(uint8_t ep_addr) { @@ -184,11 +204,18 @@ void cust_vendor_halt_cleared_cb(uint8_t ep_addr) { default: break; } + led_busy(); } // --- Control messages (see README) +#define REQUEST_SAVE_VALUE 0x01 +#define REQUEST_SAVE_DATA 0x02 +#define REQUEST_SEND_DATA 0x03 +#define REQUEST_RESET_BUFFERS 0x04 +#define REQUEST_GET_INTF_NUM 0x05 + static uint32_t saved_value = 0; bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { @@ -200,38 +227,54 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ switch (request->bRequest) { - case 0x01: + case REQUEST_SAVE_VALUE: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) { // save value from wValue saved_value = request->wValue; + led_busy(); return tud_control_status(rhport, request); } break; - case 0x02: + case REQUEST_SAVE_DATA: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 4) { // receive into `saved_value` + led_busy(); return tud_control_xfer(rhport, request, &saved_value, 4); } break; - case 0x03: + case REQUEST_SEND_DATA: if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 4) { // transmit from `saved_value` + led_busy(); return tud_control_xfer(rhport, request, &saved_value, 4); } break; - case 0x04: + case REQUEST_RESET_BUFFERS: if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) { reset_buffers(); + led_busy(); return tud_control_status(rhport, request); } break; - + + case REQUEST_GET_INTF_NUM: + if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 1) { + uint8_t intf_num = request->wIndex & 0xff; + if (intf_num < 4) { + led_busy(); + // return inteface number + return tud_control_xfer(rhport, request, &intf_num, 1); + } + } + break; + // Microsoft WCID descriptor (for automatic WinUSB installation) case WCID_VENDOR_CODE: if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wIndex == 0x0004) { + led_busy(); // transmit WCID feature descriptor int len = sizeof(wcid_feature_desc); if (len >= request->wLength) @@ -259,12 +302,7 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) { // Invoked when device is mounted void tud_mount_cb(void) { - blink_interval_ms = BLINK_MOUNTED; -} - -// Invoked when device is unmounted -void tud_umount_cb(void) { - blink_interval_ms = BLINK_NOT_MOUNTED; + is_blinking = false; } // Invoked when usb bus is suspended @@ -272,26 +310,27 @@ void tud_umount_cb(void) { // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - blink_interval_ms = BLINK_SUSPENDED; -} - -// Invoked when usb bus is resumed -void tud_resume_cb(void) { - blink_interval_ms = BLINK_MOUNTED; + board_sleep(); } // --- LED blinking --- -void led_blinking_task(void) { - static uint32_t start_ms = 0; - static bool led_state = false; - - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) - return; // not enough time - start_ms += blink_interval_ms; +void led_busy(void) { + led_on_until = board_millis() + 100; + board_led_write(true); +} - board_led_write(led_state); - led_state = 1 - led_state; // toggle +void led_blinking_task(void) { + uint32_t now = board_millis(); + if (is_blinking) { + if (has_expired(blink_toogle_at, now)) { + is_blink_on = !is_blink_on; + blink_toogle_at = now + 250; + } + board_led_write(is_blink_on && (now & 7) == 0); + + } else if (has_expired(led_on_until, now)) { + board_led_write((now & 3) == 0); + } } diff --git a/test-devices/loopback-stm32/src/usb_descriptors.c b/test-devices/loopback-stm32/src/usb_descriptors.c index 49893982..9aa5028e 100644 --- a/test-devices/loopback-stm32/src/usb_descriptors.c +++ b/test-devices/loopback-stm32/src/usb_descriptors.c @@ -57,7 +57,7 @@ enum { uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, INTF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 500), + TUD_CONFIG_DESCRIPTOR(1, INTF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 500), // Loopback interface (alternate 0) CUSTOM_VENDOR_INTERFACE(0, 4), // Loopback endpoint OUT diff --git a/test-devices/loopback-stm32/src/vendor_custom.c b/test-devices/loopback-stm32/src/vendor_custom.c index a408fc5a..cebf47b7 100644 --- a/test-devices/loopback-stm32/src/vendor_custom.c +++ b/test-devices/loopback-stm32/src/vendor_custom.c @@ -19,6 +19,8 @@ #include "device/usbd.h" #include "vendor_custom.h" +void dcd_edpt_close_all(uint8_t rhport); + static void cv_init(void); static void cv_reset(uint8_t rhport); @@ -136,6 +138,8 @@ void close_endpoints() { cv_num_eps_open -= 1; usbd_edpt_close(rhport, cv_eps_open[cv_num_eps_open]); } + + dcd_edpt_close_all(rhport); } bool cv_control_xfer(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { diff --git a/test-graalvm/README.md b/test-graalvm/README.md new file mode 100644 index 00000000..ffe37b77 --- /dev/null +++ b/test-graalvm/README.md @@ -0,0 +1,26 @@ +# Application for Testing the GraalVM Configuration + +## Collect Reachability Data + +Reachability data can be collected by running the unit test +of the _java-does-usb_ project: + +```shell +cd java-does-usb +export JAVA_TOOL_OPTIONS="-agentlib:native-image-agent=config-output-dir=metadata-{pid}-{datetime}/" +mvn test +``` + + +## Building + +```shell +mvn -Pnative package +``` + + +## Running + +```shell +./target/test_graalvm +``` diff --git a/test-graalvm/config/linux/reachability-metadata.json b/test-graalvm/config/linux/reachability-metadata.json new file mode 100644 index 00000000..e1746c04 --- /dev/null +++ b/test-graalvm/config/linux/reachability-metadata.json @@ -0,0 +1,111 @@ +{ + "foreign": { + "downcalls": [ + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jlong", + "void*" + ], + "options": { + "captureCallState": true, + "firstVariadicArg": 2 + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + } + ] + } +} \ No newline at end of file diff --git a/test-graalvm/config/macos/reachability-metadata.json b/test-graalvm/config/macos/reachability-metadata.json new file mode 100644 index 00000000..113fb587 --- /dev/null +++ b/test-graalvm/config/macos/reachability-metadata.json @@ -0,0 +1,318 @@ +{ + "foreign": { + "upcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ], + "downcalls": [ + { + "returnType": "void", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "struct(jlong,jlong)", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jdouble", + "jdouble", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jbyte", + "parameterTypes": [ + "void*", + "jlong", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)" + ] + }, + { + "returnType": "void", + "parameterTypes": [] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "jint", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ] + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "void*" + ] + }, + { + "returnType": "struct(jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte,jbyte)", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void", + "parameterTypes": [ + "void*", + "jint" + ] + } + ] + }, + "reflection": [ + { + "type": "net.codecrete.usb.macos.gen.corefoundation.CFMessagePortCreateLocal$callout$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "java.lang.foreign.MemorySegment", + "java.lang.foreign.MemorySegment" + ] + } + ] + }, + { + "type": "net.codecrete.usb.macos.gen.iokit.IOServiceAddMatchingNotification$callback$Function", + "methods": [ + { + "name": "apply", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int" + ] + } + ] + } + ] +} diff --git a/test-graalvm/config/windows/reachability-metadata.json b/test-graalvm/config/windows/reachability-metadata.json new file mode 100644 index 00000000..fe1ba6cc --- /dev/null +++ b/test-graalvm/config/windows/reachability-metadata.json @@ -0,0 +1,348 @@ +{ + "foreign": { + "upcalls": [ + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + } + ], + "downcalls": [ + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "void*", + "void*", + "jint", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "jint", + "jlong", + "jlong" + ] + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "void*", + "jlong", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "struct(jbyte,jbyte,jshort,jshort,jshort)", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "jint", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jint", + "void*", + "jint", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*" + ] + }, + { + "returnType": "void*", + "parameterTypes": [ + "jint", + "void*", + "void*", + "jint", + "jint", + "jint", + "jint", + "jint", + "void*", + "void*", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "void*", + "parameterTypes": [ + "void*", + "jint", + "jint", + "void*", + "jint", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "void*", + "void*", + "jint" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jshort", + "parameterTypes": [ + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jlong", + "void*", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "jbyte", + "void*", + "jint", + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "jint", + "void*", + "jint", + "jint", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jlong", + "parameterTypes": [ + "void*", + "void*" + ], + "options": { + "captureCallState": true + } + }, + { + "returnType": "jint", + "parameterTypes": [ + "void*", + "void*", + "jint", + "void*" + ], + "options": { + "captureCallState": true + } + } + ] + }, + "reflection": [ + { + "type": "windows.win32.ui.windowsandmessaging.WNDPROC$Function", + "methods": [ + { + "name": "invoke", + "parameterTypes": [ + "java.lang.foreign.MemorySegment", + "int", + "long", + "long" + ] + } + ] + } + ] +} diff --git a/test-graalvm/pom.xml b/test-graalvm/pom.xml new file mode 100644 index 00000000..cfaf0bbf --- /dev/null +++ b/test-graalvm/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + + net.codecrete.usb.examples + test_graalvm + jar + 1.0-SNAPSHOT + test_graalvm + https://www.github.com/manuelbl/java-does-usb + + + 25 + 25 + UTF-8 + 0.11.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + true + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + net.codecrete.usb.examples.App + true + + + + + + + + + + net.codecrete.usb + java-does-usb + 1.3.0 + + + junit + junit + 3.8.1 + test + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + compile-no-fork + + package + + + + + + + + + diff --git a/test-graalvm/src/main/java/net/codecrete/usb/examples/App.java b/test-graalvm/src/main/java/net/codecrete/usb/examples/App.java new file mode 100644 index 00000000..18dd1636 --- /dev/null +++ b/test-graalvm/src/main/java/net/codecrete/usb/examples/App.java @@ -0,0 +1,324 @@ +// +// Java Does USB +// Copyright (c) 2025 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.examples; + +import net.codecrete.usb.Usb; +import net.codecrete.usb.UsbDevice; +import net.codecrete.usb.UsbException; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static java.time.Duration.ofSeconds; + +/** + * Test for robustness when USB devices is unplugged during operation. + * + *

+ * Requires use of test device. + *

+ */ +@SuppressWarnings({"java:S106", "java:S2189"}) +public class App { + private static final Map activeDevices = new HashMap<>(); + + public static void main(String[] args) throws IOException { + System.out.println("Plug and unplug test device multiple times."); + System.out.println("Hit ENTER to exit."); + + Usb.setOnDeviceConnected(App::onPluggedDevice); + Usb.setOnDeviceDisconnected(App::onUnpluggedDevice); + Usb.getDevices().forEach(App::onPluggedDevice); + + //noinspection ResultOfMethodCallIgnored + System.in.read(); + } + + private static void onPluggedDevice(UsbDevice device) { + var config = DeviceConfig.getConfig(device); + if (config.isEmpty()) + return; + + var worker = new DeviceWorker(device, config.get()); + activeDevices.put(device, worker); + worker.start(); + } + + private static void onUnpluggedDevice(UsbDevice device) { + var config = DeviceConfig.getConfig(device); + if (config.isEmpty()) + return; + + var worker = activeDevices.remove(device); + worker.setDisconnectTime(System.currentTimeMillis()); + worker.join(); + + // test handling of disconnected devices + new Thread(() -> { + sleep(2000); + try { + device.open(); + System.err.println("Device should not be openable after disconnect"); + } catch (UsbException e) { + if (!e.getMessage().contains("disconnected")) + System.err.println("Unexpected error: " + e.getMessage()); + } + }).start(); + } + + @SuppressWarnings({"SameParameterValue", "java:S2925"}) + private static void sleep(long millis) { + try { + Thread.sleep(millis); + + } catch (InterruptedException _) { + Thread.currentThread().interrupt(); + } + } + + static class DeviceWorker { + + private final UsbDevice device; + private final DeviceConfig config; + + private final int seed; + + private long disconnectTime; + + private final Map workTracking = new HashMap<>(); + + DeviceWorker(UsbDevice device, DeviceConfig config) { + this.device = device; + this.config = config; + this.seed = (int) System.currentTimeMillis(); + } + + void start() { + System.out.println("Device connected"); + + device.open(); + device.claimInterface(config.interfaceNumber()); + + // start loopback sender and receiver + startThread((seed & 1) != 0 ? this::sendLoopbackDataStream : this::sendLoopbackData); + startThread((seed & 2) != 0 ? this::receiveLoopbackDataStream : this::receiveLoopbackData); + + // start echo sender and receiver + if (config.endpointEchoOut() > 0) { + startThread(this::sendEcho); + startThread(this::receiveEcho); + } + } + + private void startThread(Runnable action) { + var thread = new Thread(() -> runAction(action)); + var work = new Work(); + workTracking.put(thread, work); + thread.start(); + } + + void join() { + // wait for threads to finish + for (var thread : workTracking.keySet()) { + try { + boolean terminated = thread.join(ofSeconds(5)); + if (!terminated) + System.err.printf("Thread \"%s\" failed to join within 5s%n", thread.getName()); + + } catch (InterruptedException _) { + Thread.currentThread().interrupt(); + } + } + + device.close(); + + // check achieved work + for (var e : workTracking.entrySet()) { + var work = e.getValue(); + var expectedWork = work.expectedWorkPerSec * 0.001 * (work.finishTime - work.startTime); + if (work.actualWork < expectedWork) + System.err.printf("Thread \"%s\" achieved insufficient work executed. Expected: %.0f, achieved: %d%n", + e.getKey().getName(), expectedWork, work.actualWork); + } + + // check that the threads haven't terminated early + for (var e : workTracking.entrySet()) { + long duration = Math.abs(e.getValue().finishTime - disconnectTime); + if (duration > 500) + System.err.printf("Thread \"%s\" has likely crashed early%n", e.getKey().getName()); + } + + System.out.println("Device disconnected"); + } + + void setDisconnectTime(long time) { + disconnectTime = time; + } + + private synchronized void logFinish() { + var work = workTracking.get(Thread.currentThread()); + work.finishTime = System.currentTimeMillis(); + } + + private void logStart(String operation, long expectedWorkPerSec) { + Thread.currentThread().setName(operation); + var work = workTracking.get(Thread.currentThread()); + work.startTime = System.currentTimeMillis(); + work.expectedWorkPerSec = expectedWorkPerSec; + } + + private void logWork(long amount) { + var work = workTracking.get(Thread.currentThread()); + work.actualWork += amount; + } + + private void runAction(Runnable action) { + try { + action.run(); + } catch (UsbException _) { + logFinish(); + } + } + + private void sendLoopbackData() { + logStart("sending loopback data", 300_000); + var prng = new PRNG(); + var data = new byte[5000]; + //noinspection InfiniteLoopStatement + while (true) { + prng.fill(data); + device.transferOut(config.endpointLoopbackOut(), data, 1000); + logWork(data.length); + } + } + + private void receiveLoopbackData() { + logStart("receiving loopback data", 300_000); + var prng = new PRNG(); + //noinspection InfiniteLoopStatement + while (true) { + byte[] data = device.transferIn(config.endpointLoopbackIn()); + int index = prng.verify(data); + if (index >= 0) + throw new CommunicationException("invalid data received"); + logWork(data.length); + } + } + + private void sendLoopbackDataStream() { + logStart("sending loopback data with output stream", 300_000); + var prng = new PRNG(); + var data = new byte[5000]; + try (var os = device.openOutputStream(config.endpointLoopbackOut())) { + //noinspection InfiniteLoopStatement + while (true) { + prng.fill(data); + os.write(data); + logWork(data.length); + } + } catch (IOException e) { + throw new CommunicationException(e); + } + } + + private void receiveLoopbackDataStream() { + logStart("receiving loopback data with input stream", 300_000); + var prng = new PRNG(); + try (var is = device.openInputStream(config.endpointLoopbackIn())) { + //noinspection InfiniteLoopStatement + while (true) { + var data = new byte[2000]; + int n = is.read(data); + int index = prng.verify(data, n); + if (index >= 0) + throw new CommunicationException("invalid data received"); + logWork(n); + } + } catch (IOException e) { + throw new CommunicationException(e); + } + } + + private void sendEcho() { + logStart("sending echo", 7); + var data = new byte[]{0x03, 0x45, 0x73, (byte) 0xb3, (byte) 0x9f, 0x3f, 0x00, 0x6a}; + //noinspection InfiniteLoopStatement + while (true) { + device.transferOut(config.endpointEchoOut(), data); + logWork(1); + sleep(100); + } + } + + private void receiveEcho() { + logStart("receiving echo", 14); + //noinspection InfiniteLoopStatement + while (true) { + device.transferIn(config.endpointEchoIn()); + logWork(1); + } + } + } + + static class Work { + long startTime; + long expectedWorkPerSec; + long actualWork; + long finishTime; + } + + /** + * Pseudo random number generator + */ + static class PRNG { + private int state; + private int nBytes; + private int bits; + + int next() { + int x = state; + x ^= x << 13; + x ^= x >>> 17; + x ^= x << 5; + state = x; + return x; + } + + void fill(byte[] data) { + int len = data.length; + for (int i = 0; i < len; i++) { + if (nBytes == 0) { + bits = next(); + nBytes = 4; + } + data[i] = (byte) bits; + bits >>>= 8; + nBytes--; + } + } + + int verify(byte[] data) { + return verify(data, data.length); + } + + int verify(byte[] data, int len) { + for (int i = 0; i < len; i++) { + if (nBytes == 0) { + bits = next(); + nBytes = 4; + } + if (data[i] != (byte) bits) + return i; + bits >>>= 8; + nBytes--; + } + return -1; + } + } +} diff --git a/test-graalvm/src/main/java/net/codecrete/usb/examples/CommunicationException.java b/test-graalvm/src/main/java/net/codecrete/usb/examples/CommunicationException.java new file mode 100644 index 00000000..d8660f7f --- /dev/null +++ b/test-graalvm/src/main/java/net/codecrete/usb/examples/CommunicationException.java @@ -0,0 +1,21 @@ +// +// Java Does USB +// Copyright (c) 2025 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// + +package net.codecrete.usb.examples; + +import java.io.IOException; + +public class CommunicationException extends RuntimeException { + + public CommunicationException(String message) { + super(message); + } + + public CommunicationException(IOException cause) { + super("Error in communication with USB device", cause); + } +} diff --git a/test-graalvm/src/main/java/net/codecrete/usb/examples/DeviceConfig.java b/test-graalvm/src/main/java/net/codecrete/usb/examples/DeviceConfig.java new file mode 100644 index 00000000..05bf8bdd --- /dev/null +++ b/test-graalvm/src/main/java/net/codecrete/usb/examples/DeviceConfig.java @@ -0,0 +1,68 @@ +// +// Java Does USB +// Copyright (c) 2025 Manuel Bleichenbacher +// Licensed under MIT License +// https://opensource.org/licenses/MIT +// +// Configuration information about test device +// + +package net.codecrete.usb.examples; + +import net.codecrete.usb.UsbDevice; + +import java.util.Optional; +import java.util.stream.Stream; + +/** + * Test device configuration + * @param vid vendor ID + * @param pid product ID + * @param isComposite indicates if this is the composite test device + * @param interfaceNumber interface number for loopback and echo endpoints + * @param endpointLoopbackOut loopback OUT endpoint number + * @param endpointLoopbackIn loopback IN endpoint number + * @param endpointEchoOut echo OUT endpoint number + * @param endpointEchoIn echo IN endpoint number + */ +public record DeviceConfig(int vid, int pid, + boolean isComposite, + int interfaceNumber, + int endpointLoopbackOut, int endpointLoopbackIn, + int endpointEchoOut, int endpointEchoIn +) { + + private static final DeviceConfig LOOPBACK_DEVICE = new DeviceConfig( + 0xcafe, + 0xceaf, + false, + 0, + 1, + 2, + 3, + 3 + ); + + private static final DeviceConfig COMPOSITE_DEVICE = new DeviceConfig( + 0xcafe, + 0xcea0, + true, + 3, + 1, + 2, + -1, + -1 + ); + + + /** + * Gets the configuration fo the specified USB device. + * @param device USB device + * @return configuration, or empty if the USB device is not a test device + */ + public static Optional getConfig(UsbDevice device) { + return Stream.of(LOOPBACK_DEVICE, COMPOSITE_DEVICE) + .filter(config -> device.getVendorId() == config.vid() && device.getProductId() == config.pid()) + .findFirst(); + } +} diff --git a/test-graalvm/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/test_graalvm/native-image.properties b/test-graalvm/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/test_graalvm/native-image.properties new file mode 100644 index 00000000..4e4f3471 --- /dev/null +++ b/test-graalvm/src/main/resources/META-INF/native-image/net.codecrete.usb.examples/test_graalvm/native-image.properties @@ -0,0 +1 @@ +Args = --enable-native-access=ALL-UNNAMED -H:ConfigurationFileDirectories=config/macos