mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-14 04:18:56 +00:00
Merge branch 'master' into zhangslice-master
This commit is contained in:
commit
3333703d25
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,35 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: 'Please provide all details at least for Setup/Describe/Reproduce'
|
||||
labels: Bug 🐞
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Set Up**
|
||||
|
||||
- **PC OS** e.g Ubuntu 20.04 / Windows 10 / macOS 10.15
|
||||
- **Board** e.g Feather nRF52840 Express (if custom specify your MCUs)
|
||||
- **TinyUSB version** relase version or git hash (preferrably running with master for lastest code)
|
||||
- **Firmware** e.g examples/device/cdc_msc
|
||||
|
||||
**Describe The Bug**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. See error
|
||||
|
||||
**Screenshots**
|
||||
|
||||
If applicable, add screenshots, bus capture to help explain your problem.
|
||||
|
||||
**Log**
|
||||
|
||||
If applicable, provide the stack's log (uart/rtt/swo) where the issue occurred as attached txt file, best with comments to explain the actual events.
|
||||
Note: To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. More information can be found at [example's readme](/docs/getting_started.md)
|
74
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
74
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
name: Bug Report
|
||||
description: Report a problem with TinyUSB
|
||||
labels: 'Bug 🐞'
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
It's okay to leave some blank if it doesn't apply to your problem.
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Operating System
|
||||
options:
|
||||
- Linux
|
||||
- MacOS
|
||||
- RaspberryPi OS
|
||||
- Windows 7
|
||||
- Windows 10
|
||||
- Windows 11
|
||||
- Others
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Board
|
||||
placeholder: e.g Feather nRF52840 Express
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Firmware
|
||||
placeholder: |
|
||||
e.g examples/device/cdc_msc.
|
||||
If it is custom firmware, please provide links to your minimal sources or as attached files.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What happened ?
|
||||
placeholder: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: How to reproduce ?
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Debug Log
|
||||
placeholder: |
|
||||
TinyUSB debug log where the issue occurred as attached txt file, best with comments to explain the actual events.
|
||||
|
||||
Note: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h.
|
||||
More information can be found at [example's readme](https://github.com/hathach/tinyusb/blob/master/docs/getting_started.md)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
validations:
|
||||
required: false
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -49,8 +49,9 @@ jobs:
|
||||
- 'samd11'
|
||||
- 'samd21'
|
||||
- 'samd51'
|
||||
- 'saml22'
|
||||
- 'saml2x'
|
||||
- 'stm32f0'
|
||||
- 'stm32f1'
|
||||
- 'stm32f4'
|
||||
- 'stm32f7'
|
||||
- 'stm32h7'
|
||||
|
4
.github/workflows/build_esp.yml
vendored
4
.github/workflows/build_esp.yml
vendored
@ -16,10 +16,10 @@ jobs:
|
||||
board:
|
||||
# Alphabetical order
|
||||
# ESP32-S2
|
||||
- 'adafruit_metro_esp32s2'
|
||||
- 'espressif_saola_1'
|
||||
# ESP32-S3
|
||||
- 'espressif_addax_1'
|
||||
# latest IDF does not define USB0 in linker
|
||||
#- 'espressif_addax_1'
|
||||
|
||||
steps:
|
||||
- name: Setup Python
|
||||
|
2
.github/workflows/build_renesas.yml
vendored
2
.github/workflows/build_renesas.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
matrix:
|
||||
family:
|
||||
# Alphabetical order
|
||||
- 'rx63n'
|
||||
- 'rx'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
1
.github/workflows/build_riscv.yml
vendored
1
.github/workflows/build_riscv.yml
vendored
@ -16,6 +16,7 @@ jobs:
|
||||
family:
|
||||
# Alphabetical order
|
||||
- 'fomu'
|
||||
- 'gd32vf103'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -124,3 +124,6 @@
|
||||
[submodule "hw/mcu/mindmotion/mm32sdk"]
|
||||
path = hw/mcu/mindmotion/mm32sdk
|
||||
url = https://github.com/zhangslice/mm32sdk.git
|
||||
[submodule "hw/mcu/gd/nuclei-sdk"]
|
||||
path = hw/mcu/gd/nuclei-sdk
|
||||
url = https://github.com/Nuclei-Software/nuclei-sdk.git
|
||||
|
18
.readthedocs.yaml
Normal file
18
.readthedocs.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
version: 2
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
submodules:
|
||||
include: []
|
||||
recursive: false
|
||||
|
@ -1,76 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at thach@tinyusb.org. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
88
CODE_OF_CONDUCT.rst
Normal file
88
CODE_OF_CONDUCT.rst
Normal file
@ -0,0 +1,88 @@
|
||||
***************
|
||||
Code of Conduct
|
||||
***************
|
||||
|
||||
Our Pledge
|
||||
----------
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our
|
||||
project and our community a harassment-free experience for everyone,
|
||||
regardless of age, body size, disability, ethnicity, sex
|
||||
characteristics, gender identity and expression, level of experience,
|
||||
education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.
|
||||
|
||||
Our Standards
|
||||
-------------
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual
|
||||
attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political
|
||||
attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or
|
||||
electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
Our Responsibilities
|
||||
--------------------
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of
|
||||
acceptable behavior and are expected to take appropriate and fair
|
||||
corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit,
|
||||
or reject comments, commits, code, wiki edits, issues, and other
|
||||
contributions that are not aligned to this Code of Conduct, or to ban
|
||||
temporarily or permanently any contributor for other behaviors that they
|
||||
deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
Scope
|
||||
-----
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public
|
||||
spaces when an individual is representing the project or its community.
|
||||
Examples of representing a project or community include using an
|
||||
official project e-mail address, posting via an official social media
|
||||
account, or acting as an appointed representative at an online or
|
||||
offline event. Representation of a project may be further defined and
|
||||
clarified by project maintainers.
|
||||
|
||||
Enforcement
|
||||
-----------
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may
|
||||
be reported by contacting the project team at thach@tinyusb.org. All
|
||||
complaints will be reviewed and investigated and will result in a
|
||||
response that is deemed necessary and appropriate to the circumstances.
|
||||
The project team is obligated to maintain confidentiality with regard to
|
||||
the reporter of an incident. Further details of specific enforcement
|
||||
policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in
|
||||
good faith may face temporary or permanent repercussions as determined
|
||||
by other members of the project's leadership.
|
||||
|
||||
Attribution
|
||||
-----------
|
||||
|
||||
This Code of Conduct is adapted from the `Contributor
|
||||
Covenant <https://www.contributor-covenant.org>`__, version 1.4,
|
||||
available at
|
||||
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
@ -1,97 +0,0 @@
|
||||
# TinyUSB contributors (sorted alphabetically)
|
||||
|
||||
- **[Adafruit Team](https://github.com/adafruit)**
|
||||
- Main supporter and sponsor for hardware boards and kits
|
||||
- Discussion and suggestion for feature and improvement
|
||||
- Design the project logo
|
||||
|
||||
- **[Ha Thach](https://github.com/hathach)**
|
||||
- *Author and maintainer*
|
||||
- Most features development
|
||||
|
||||
- **[Hristo Gochkov](https://github.com/me-no-dev)**
|
||||
- Improve ESP32s2 DCD
|
||||
|
||||
- **[Jan Dümpelmann](https://github.com/duempel)**
|
||||
- Improve transfer performance for Synopsys DCD for STM32 MCUs
|
||||
|
||||
- **[Jeff Epler](https://github.com/jepler)**
|
||||
- Improve MIDI class driver
|
||||
|
||||
- **[Jerzy Kasenberg](https://github.com/kasjer)**
|
||||
- Add new DCD port for **Dialog DA1469x**
|
||||
- Add new class driver for **Bluetooth HCI**
|
||||
- Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x
|
||||
- Improve Audio driver and add uac2_headset example
|
||||
- Improve STM32 Synopsys DCD with various PRs
|
||||
|
||||
- **[J McCarthy](https://github.com/xmos-jmccarthy)**
|
||||
- Add new DFU 1.1 class driver
|
||||
- Add new example for dfu
|
||||
|
||||
- **[Kamil Tomaszewski](https://github.com/kamtom480)**
|
||||
- Add new DCD port for **Sony CXD56** (spresnese board)
|
||||
|
||||
- **[Kay Sievers](https://github.com/kaysievers)**
|
||||
- Improve MIDI driver with packet API
|
||||
|
||||
- **[Koji KITAYAMA](https://github.com/kkitayam)**
|
||||
- Add new DCD port for **NXP Kinetis KL25**
|
||||
- Add new DCD port for **Renesas RX63n** with GR-CITRUS board
|
||||
|
||||
- **[Nathan Conrad](https://github.com/pigrew)**
|
||||
- Add new DCD port for **STM32 fsdev** Fullspeed device for STM32 L0, F0, F1, F3 etc ...
|
||||
- Add new class driver for **USB Test and Measurement Class (USBTMC)**
|
||||
- Various improvement e.g Zero-length packet, Lint setup
|
||||
- Board support for STM32F070RB Nucleo, STM32F303 Discovery
|
||||
|
||||
- **[Peter Lawrence](https://github.com/majbthrd)**
|
||||
- Add new DCD port for **Nuvoton NUC 120, 121, 125, 126, 505**
|
||||
- Add new class driver for **USBNET RNDIS, CDC-ECM**
|
||||
- Add *net_lwip_webserver* example for demonstration of usbnet with lwip
|
||||
- Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505
|
||||
- Improve multiple cdc interfaces API & add cdc_dual_ports example
|
||||
|
||||
- **[Rafael Silva](https://github.com/perigoso)**
|
||||
- Add new DCD port for **Silabs EFM32GG12** with SLTB009A board
|
||||
|
||||
- **[Raspberry Pi Team](https://github.com/raspberrypi)**
|
||||
- Add new DCD port for **Raspberry Pi RP2040**
|
||||
- Add new HCD port for **Raspberry Pi RP2040**
|
||||
|
||||
- **[Reinhard Panhuber](https://github.com/PanRe)**
|
||||
- Add new class driver for **USB Audio Class 2.0 (UAC2)**
|
||||
- Rework tu_fifo with unmasked pointer, add DMA support, and constant address support
|
||||
- Add new DCD/USBD edpt_xfer_fifo() API for optimizing endpoint transfer
|
||||
- Add and greatly improve Isochronous transfer
|
||||
- Add new audio examples: audio_test and audio_4_channel_mic
|
||||
|
||||
- **[Scott Shawcroft](https://github.com/tannewt)**
|
||||
- Add new DCD port for **SAMD21 and SAMD51**
|
||||
- Add new class driver for **Musical Instrument Digital Interface (MIDI)**
|
||||
- Improve USBD control transfer, MSC, CDC class driver
|
||||
- Board support for Metro M0 & M4 express
|
||||
- Write the excellent porting.md documentation
|
||||
- Add initial Makefile
|
||||
|
||||
- **[Sean Cross](https://github.com/xobs)**
|
||||
- Add new DCD port for **ValentyUSB eptri** (fomu board)
|
||||
|
||||
- **[Sylvain "tnt" Munaut](https://github.com/smunaut)**
|
||||
- Add new class driver for DFU Runtime
|
||||
|
||||
- **[Timon Skerutsch](https://github.com/PTS93)**
|
||||
- Add hid_test.js script and extensive test for bi-directional raw HID
|
||||
|
||||
- **[Tod E. Kurt](https://github.com/todbot)**
|
||||
- Add hid_test.js script and extensive test for bi-directional raw HID
|
||||
|
||||
- **[Uwe Bonnes](https://github.com/UweBonnes)**
|
||||
- Improve STM32 Synopsys highspeed DCD
|
||||
|
||||
- **[William D. Jones](https://github.com/cr1901)**
|
||||
- Add new DCD port for **Synopsys DesignWare** for STM32 L4, F2, F4, F7, H7 etc ...
|
||||
- Add new DCD port for **TI MSP430**
|
||||
- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp_exp430f5529lp etc ...
|
||||
|
||||
**[Full contributors list](https://github.com/hathach/tinyusb/contributors).**
|
189
CONTRIBUTORS.rst
Normal file
189
CONTRIBUTORS.rst
Normal file
@ -0,0 +1,189 @@
|
||||
************
|
||||
Contributors
|
||||
************
|
||||
|
||||
Special thanks to all the people who spent their precious time and effort to help this project so far.
|
||||
list contributors and their awesome work for the stack:
|
||||
|
||||
Notable contributors
|
||||
====================
|
||||
|
||||
(sorted alphabetically)
|
||||
|
||||
`Adafruit Team <https://github.com/adafruit>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Main supporter and sponsor for hardware boards and kits
|
||||
- Discussion and suggestion for feature and improvement
|
||||
- Design the project logo
|
||||
|
||||
|
||||
`Ha Thach <https://github.com/hathach>`__
|
||||
-----------------------------------------
|
||||
|
||||
- *Author and maintainer*
|
||||
- Most features development
|
||||
|
||||
|
||||
`Hristo Gochkov <https://github.com/me-no-dev>`__
|
||||
-------------------------------------------------
|
||||
|
||||
- Improve ESP32s2 DCD
|
||||
|
||||
|
||||
`Jan Dümpelmann <https://github.com/duempel>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Improve transfer performance for Synopsys DCD for STM32 MCUs
|
||||
|
||||
|
||||
`Jeff Epler <https://github.com/jepler>`__
|
||||
------------------------------------------
|
||||
|
||||
- Improve MIDI class driver
|
||||
|
||||
|
||||
`Jerzy Kasenberg <https://github.com/kasjer>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Add new DCD port for Dialog DA1469x
|
||||
- Add new class driver for Bluetooth HCI
|
||||
- Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x
|
||||
- Improve Audio driver and add uac2\_headset example
|
||||
- Improve STM32 Synopsys DCD with various PRs
|
||||
|
||||
|
||||
`J McCarthy <https://github.com/xmos-jmccarthy>`__
|
||||
--------------------------------------------------
|
||||
|
||||
- Add new DFU 1.1 class driver
|
||||
- Add new example for dfu
|
||||
|
||||
|
||||
`Kamil Tomaszewski <https://github.com/kamtom480>`__
|
||||
----------------------------------------------------
|
||||
|
||||
- Add new DCD port for Sony CXD56 (spresnese board)
|
||||
|
||||
|
||||
`Kay Sievers <https://github.com/kaysievers>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Improve MIDI driver with packet API
|
||||
|
||||
|
||||
`Koji KITAYAMA <https://github.com/kkitayam>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Add new DCD port for NXP Kinetis KL25
|
||||
- Add new DCD port for Renesas RX63n with GR-CITRUS board
|
||||
|
||||
|
||||
`Nathan Conrad <https://github.com/pigrew>`__
|
||||
---------------------------------------------
|
||||
|
||||
- Add new DCD port for STM32 fsdev Fullspeed device for STM32 L0,
|
||||
F0, F1, F3 etc ...
|
||||
- Add new class driver for USB Test and Measurement Class (USBTMC)
|
||||
- Various improvement e.g Zero-length packet, Lint setup
|
||||
- Board support for STM32F070RB Nucleo, STM32F303 Discovery
|
||||
|
||||
|
||||
`Peter Lawrence <https://github.com/majbthrd>`__
|
||||
------------------------------------------------
|
||||
|
||||
- Add new DCD port for Nuvoton NUC 120, 121, 125, 126, 505
|
||||
- Add new class driver for USBNET RNDIS, CDC-ECM
|
||||
- Add *net\_lwip\_webserver* example for demonstration of usbnet with
|
||||
lwip
|
||||
- Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505
|
||||
- Improve multiple cdc interfaces API & add cdc\_dual\_ports example
|
||||
|
||||
|
||||
`Rafael Silva <https://github.com/perigoso>`__
|
||||
----------------------------------------------
|
||||
|
||||
- Add new DCD port for Silabs EFM32GG12 with SLTB009A board
|
||||
- Rewrite documentation in rst and setup for readthedocs
|
||||
|
||||
|
||||
`Raspberry Pi Team <https://github.com/raspberrypi>`__
|
||||
------------------------------------------------------
|
||||
|
||||
- Add new DCD port for Raspberry Pi RP2040
|
||||
- Add new HCD port for Raspberry Pi RP2040
|
||||
|
||||
|
||||
`Reinhard Panhuber <https://github.com/PanRe>`__
|
||||
------------------------------------------------
|
||||
|
||||
- Add new class driver for USB Audio Class 2.0 (UAC2)
|
||||
- Rework tu\_fifo with unmasked pointer, add DMA support, and constant
|
||||
address support
|
||||
- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint
|
||||
transfer
|
||||
- Add and greatly improve Isochronous transfer
|
||||
- Add new audio examples: audio\_test and audio\_4\_channel\_mic
|
||||
|
||||
|
||||
`Scott Shawcroft <https://github.com/tannewt>`__
|
||||
------------------------------------------------
|
||||
|
||||
- Add new DCD port for SAMD21 and SAMD51
|
||||
- Add new class driver for Musical Instrument Digital Interface
|
||||
(MIDI)
|
||||
- Improve USBD control transfer, MSC, CDC class driver
|
||||
- Board support for Metro M0 & M4 express
|
||||
- Write the excellent porting.md documentation
|
||||
- Add initial Makefile
|
||||
|
||||
`Sean Cross <https://github.com/xobs>`__
|
||||
----------------------------------------
|
||||
|
||||
- Add new DCD port for ValentyUSB eptri (fomu board)
|
||||
|
||||
|
||||
`Sylvain "tnt" Munaut <https://github.com/smunaut>`__
|
||||
-----------------------------------------------------
|
||||
|
||||
- Add new class driver for DFU Runtime
|
||||
|
||||
|
||||
`Timon Skerutsch <https://github.com/PTS93>`__
|
||||
----------------------------------------------
|
||||
|
||||
- Add hid\_test.js script and extensive test for bi-directional raw HID
|
||||
|
||||
|
||||
`Tod E. Kurt <https://github.com/todbot>`__
|
||||
-------------------------------------------
|
||||
|
||||
- Add hid\_test.js script and extensive test for bi-directional raw HID
|
||||
|
||||
|
||||
`Uwe Bonnes <https://github.com/UweBonnes>`__
|
||||
---------------------------------------------
|
||||
|
||||
- Improve STM32 Synopsys highspeed DCD
|
||||
|
||||
|
||||
`William D. Jones <https://github.com/cr1901>`__
|
||||
------------------------------------------------
|
||||
|
||||
- Add new DCD port for Synopsys DesignWare for STM32 L4, F2, F4,
|
||||
F7, H7 etc ...
|
||||
- Add new DCD port for TI MSP430
|
||||
- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard
|
||||
v1.1, msp\_exp430f5529lp etc ...
|
||||
|
||||
|
||||
`Zixun Li <https://github.com/HiFiPhile>`__
|
||||
-----------------------------------------------
|
||||
|
||||
- Add new DCD port for Microchip SAMx7x
|
||||
- Add IAR compiler support
|
||||
- Improve UAC2, CDC, DFU class driver
|
||||
|
||||
|
||||
`Full contributors list <https://github.com/hathach/tinyusb/contributors>`__
|
||||
============================================================================
|
111
README.md
111
README.md
@ -1,111 +0,0 @@
|
||||
# TinyUSB
|
||||
|
||||

|
||||
|
||||
[](https://github.com/hathach/tinyusb/actions) [](https://opensource.org/licenses/MIT)
|
||||
|
||||
TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function.
|
||||
|
||||

|
||||
|
||||
```
|
||||
.
|
||||
├── docs # Documentation
|
||||
├── examples # Sample with Makefile build support
|
||||
├── hw
|
||||
│ ├── bsp # Supported boards source files
|
||||
│ └── mcu # Low level mcu core & peripheral drivers
|
||||
├── lib # Sources from 3rd party such as freeRTOS, fatfs ...
|
||||
├── src # All sources files for TinyUSB stack itself.
|
||||
├── test # Unit tests for the stack
|
||||
└── tools # Files used internally
|
||||
```
|
||||
|
||||
## Contributors
|
||||
|
||||
Special thanks to all the people who spent their precious time and effort to help this project so far. Check out the
|
||||
[CONTRIBUTORS.md](CONTRIBUTORS.md) file for the list of all contributors and their awesome work for the stack.
|
||||
|
||||
## Supported MCUs
|
||||
|
||||
The stack supports the following MCUs:
|
||||
|
||||
- **Dialog:** DA1469x
|
||||
- **Espressif:** ESP32-S2, ESP32-S3
|
||||
- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55
|
||||
- **NordicSemi:** nRF52833, nRF52840
|
||||
- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
|
||||
- **NXP:**
|
||||
- iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
|
||||
- Kinetis: KL25
|
||||
- LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
|
||||
- **Raspberry Pi:** RP2040
|
||||
- **Renesas:** RX63N
|
||||
- **Silabs:** EFM32GG12
|
||||
- **Sony:** CXD56
|
||||
- **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 both FullSpeed and HighSpeed
|
||||
- **TI:** MSP430
|
||||
- **[ValentyUSB](https://github.com/im-tomu/valentyusb)** eptri
|
||||
|
||||
[Here is the list of supported Boards](docs/boards.md) that can be used with provided examples.
|
||||
|
||||
## Device Stack
|
||||
|
||||
Supports multiple device configurations by dynamically changing usb descriptors. Low power functions such like suspend, resume, and remote wakeup. Following device classes are supported:
|
||||
|
||||
- Audio Class 2.0 (UAC2) still work in progress
|
||||
- Bluetooth Host Controller Interface (BTH HCI)
|
||||
- Communication Class (CDC)
|
||||
- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme
|
||||
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
|
||||
- Mass Storage Class (MSC): with multiple LUNs
|
||||
- Musical Instrument Digital Interface (MIDI)
|
||||
- Network with RNDIS, CDC-ECM (work in progress)
|
||||
- USB Test and Measurement Class (USBTMC)
|
||||
- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
|
||||
- [WebUSB](https://github.com/WICG/webusb) with vendor-specific class
|
||||
|
||||
If you have special need, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how RPi team add their reset interface [raspberrypi/pico-sdk#197](https://github.com/raspberrypi/pico-sdk/pull/197)
|
||||
|
||||
## Host Stack
|
||||
|
||||
**Most active development is on the Device stack. The Host stack is under rework and largely untested.**
|
||||
|
||||
- Human Interface Device (HID): Keyboard, Mouse, Generic
|
||||
- Mass Storage Class (MSC)
|
||||
- Hub currently only supports 1 level of hub (due to my laziness)
|
||||
|
||||
## OS Abstraction layer
|
||||
|
||||
TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box.
|
||||
|
||||
- **No OS**
|
||||
- **FreeRTOS**
|
||||
- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example)
|
||||
|
||||
## Getting Started
|
||||
|
||||
[Here are the details for getting started](docs/getting_started.md) with the stack.
|
||||
|
||||
## Porting
|
||||
|
||||
Want to help add TinyUSB support for a new MCU? Read [here](docs/porting.md) for an explanation on the low-level API needed by TinyUSB.
|
||||
|
||||
## License
|
||||
|
||||
MIT license for all TinyUSB sources `src` folder, [Full license is here](LICENSE). However, each file is individually licensed especially those in `lib` and `hw/mcu` folder. Please make sure you understand all the license term for files you use in your project.
|
||||
|
||||
## Uses
|
||||
|
||||
TinyUSB is currently used by these other projects:
|
||||
|
||||
- [Adafruit nRF52 Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
|
||||
- [Adafruit nRF52 Bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader)
|
||||
- [Adafruit SAMD Arduino](https://github.com/adafruit/ArduinoCore-samd)
|
||||
- [CircuitPython](https://github.com/adafruit/circuitpython)
|
||||
- [Espressif IDF](https://github.com/espressif/esp-idf)
|
||||
- [MicroPython](https://github.com/micropython/micropython)
|
||||
- [mynewt](https://mynewt.apache.org)
|
||||
- [Raspberry Pi Pico SDK](https://github.com/raspberrypi/pico-sdk)
|
||||
- [TinyUF2 Bootloader](https://github.com/adafruit/tinyuf2)
|
||||
- [TinyUSB Arduino Library](https://github.com/adafruit/Adafruit_TinyUSB_Arduino)
|
140
README.rst
Normal file
140
README.rst
Normal file
@ -0,0 +1,140 @@
|
||||
.. figure:: docs/assets/logo.svg
|
||||
:alt: TinyUSB
|
||||
|
||||
|Build Status| |Documentation Status| |License|
|
||||
|
||||
TinyUSB is an open-source cross-platform USB Host/Device stack for
|
||||
embedded system, designed to be memory-safe with no dynamic allocation
|
||||
and thread-safe with all interrupt events are deferred then handled in
|
||||
the non-ISR task function.
|
||||
|
||||
Please take a look at the online `documentation <https://docs.tinyusb.org/>`__.
|
||||
|
||||
.. figure:: docs/assets/stack.svg
|
||||
:width: 500px
|
||||
:alt: stackup
|
||||
|
||||
::
|
||||
|
||||
.
|
||||
├── docs # Documentation
|
||||
├── examples # Sample with Makefile build support
|
||||
├── hw
|
||||
│ ├── bsp # Supported boards source files
|
||||
│ └── mcu # Low level mcu core & peripheral drivers
|
||||
├── lib # Sources from 3rd party such as freeRTOS, fatfs ...
|
||||
├── src # All sources files for TinyUSB stack itself.
|
||||
├── test # Unit tests for the stack
|
||||
└── tools # Files used internally
|
||||
|
||||
Supported MCUs
|
||||
==============
|
||||
|
||||
The stack supports the following MCUs:
|
||||
|
||||
- **Dialog:** DA1469x
|
||||
- **Espressif:** ESP32-S2, ESP32-S3
|
||||
- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x
|
||||
- **NordicSemi:** nRF52833, nRF52840
|
||||
- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
|
||||
- **NXP:**
|
||||
|
||||
- iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
|
||||
- Kinetis: KL25, K32L2Bxx
|
||||
- LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
|
||||
|
||||
- **Raspberry Pi:** RP2040
|
||||
- **Renesas:** RX63N, RX65N
|
||||
- **Silabs:** EFM32GG12
|
||||
- **Sony:** CXD56
|
||||
- **ST:** STM32 series: L0, L1, F0, F1, F2, F3, F4, F7, H7 both FullSpeed and HighSpeed
|
||||
- **TI:** MSP430
|
||||
- **ValentyUSB:** eptri
|
||||
|
||||
Here is the list of `Supported Devices`_ that can be used with provided examples.
|
||||
|
||||
Device Stack
|
||||
============
|
||||
|
||||
Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported:
|
||||
|
||||
- Audio Class 2.0 (UAC2)
|
||||
- Bluetooth Host Controller Interface (BTH HCI)
|
||||
- Communication Device Class (CDC)
|
||||
- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme
|
||||
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
|
||||
- Mass Storage Class (MSC): with multiple LUNs
|
||||
- Musical Instrument Digital Interface (MIDI)
|
||||
- Network with RNDIS, CDC-ECM (work in progress)
|
||||
- USB Test and Measurement Class (USBTMC)
|
||||
- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
|
||||
- `WebUSB <https://github.com/WICG/webusb>`__ with vendor-specific class
|
||||
|
||||
If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface [raspberrypi/pico-sdk#197](https://github.com/raspberrypi/pico-sdk/pull/197)
|
||||
|
||||
Host Stack
|
||||
==========
|
||||
|
||||
- Human Interface Device (HID): Keyboard, Mouse, Generic
|
||||
- Mass Storage Class (MSC)
|
||||
- Hub currently only supports 1 level of hub (due to my laziness)
|
||||
|
||||
OS Abstraction layer
|
||||
====================
|
||||
|
||||
TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box.
|
||||
|
||||
- **No OS**
|
||||
- **FreeRTOS**
|
||||
- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example)
|
||||
|
||||
Local Docs
|
||||
==========
|
||||
|
||||
- Info
|
||||
|
||||
- `Uses`_
|
||||
- `Changelog`_
|
||||
- `Contributors`_
|
||||
|
||||
- `Reference`_
|
||||
|
||||
- `Supported Devices`_
|
||||
- `Getting Started`_
|
||||
- `Concurrency`_
|
||||
|
||||
- `Contributing`_
|
||||
|
||||
- `Code of Conduct`_
|
||||
- `Structure`_
|
||||
- `Porting`_
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
All TinyUSB sources in the ``src`` folder are licensed under MIT
|
||||
license, the `Full license is here <LICENSE>`__. However, each file can be
|
||||
individually licensed especially those in ``lib`` and ``hw/mcu`` folder.
|
||||
Please make sure you understand all the license term for files you use
|
||||
in your project.
|
||||
|
||||
|
||||
.. |Build Status| image:: https://github.com/hathach/tinyusb/workflows/Build/badge.svg
|
||||
:target: https://github.com/hathach/tinyusb/actions
|
||||
.. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest
|
||||
:target: https://docs.tinyusb.org/en/latest/?badge=latest
|
||||
.. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg
|
||||
:target: https://opensource.org/licenses/MIT
|
||||
|
||||
|
||||
.. _Uses: docs/info/uses.rst
|
||||
.. _Changelog: docs/info/changelog.rst
|
||||
.. _Contributors: CONTRIBUTORS.rst
|
||||
.. _Reference: docs/reference/index.rst
|
||||
.. _Supported Devices: docs/reference/supported.rst
|
||||
.. _Getting Started: docs/reference/getting_started.rst
|
||||
.. _Concurrency: docs/reference/concurrency.rst
|
||||
.. _Contributing: docs/contributing/index.rst
|
||||
.. _Code of Conduct: CODE_OF_CONDUCT.rst
|
||||
.. _Structure: docs/contributing/structure.rst
|
||||
.. _Porting: docs/contributing/porting.rst
|
18
docs/assets/logo.svg
Normal file
18
docs/assets/logo.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="280" height="140" version="1.1" viewBox="0 0 74.083 37.042" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-60.931 -79.245)">
|
||||
<g transform="matrix(1.0442 0 0 1.1531 -27.105 33.588)" fill="#fff">
|
||||
<path d="m86.972 39.594c-1.4683 3.2e-5 -2.6588 1.181-2.66 2.6384v26.844c3.3e-5 1.4583 1.1909 2.6404 2.66 2.6404h65.63c1.469-3.2e-5 2.66-1.1822 2.66-2.6404v-26.844c-1e-3 -1.4575-1.1917-2.6384-2.66-2.6384z" color="#000000" fill="#fff" style="-inkscape-stroke:none"/>
|
||||
</g>
|
||||
<g transform="matrix(.35278 0 0 -.35278 -160.36 421.93)" fill="#231f20">
|
||||
<path transform="translate(672.09 955.48)" d="m0 0h-21.484v-12.601h-5.349v-6.436h5.349v-25.383c0-11.331 7.252-13.87 17.223-13.87 4.352 0 8.613 0.272 12.873 0.907v6.073c-0.816-0.09-2.266-0.362-3.535-0.362-3.807 0-5.077 0.816-5.077 4.896v27.739h8.612v6.436h-8.612z"/>
|
||||
<path transform="translate(693.61 925.33)" d="m0 0h-0.049c-1.518 0-2.165-0.896-2.165-2.24v-0.05h4.504v0.05c0 1.344-0.771 2.24-2.29 2.24"/>
|
||||
<path transform="translate(700.92 925.5)" d="m0 0h-0.124c-1.443 0-2.265-0.995-2.265-2.389v-0.074h4.654v0.074c0 1.394-0.822 2.389-2.265 2.389"/>
|
||||
<path transform="translate(750.09 943.78)" d="m0 0c-6.165 0-11.876-2.267-14.505-5.893v4.986h-20.578v-45.326h21.484v36.533c1.27 0.272 2.449 0.453 3.717 0.453 4.715 0 5.44-2.538 5.44-6.436v-30.55h21.484v30.278c0 11.694-7.523 15.955-17.042 15.955"/>
|
||||
<path transform="translate(811.83 942.88)" d="m0 0-10.516-23.57-11.784 23.57h-23.388l24.204-48.046-6.799-15.411h8.249l28.193 63.457z"/>
|
||||
<path transform="translate(706 920)" d="m0 0h-17.421v2.637c0 2.938 1.194 5.675 4.43 5.675h0.124c2.24 0 3.335-1.269 3.932-2.514 0.647 1.469 1.667 2.738 3.883 2.738h0.224c3.086 0 4.828-2.39 4.828-5.774zm-0.598-9.412h-3.16c0.622 1.07 0.971 1.917 0.971 2.737 0 0.871-0.424 1.618-1.493 1.618h-0.05c-0.797 0-1.394-0.249-3.037-1.692-2.339-2.065-3.459-2.912-5.574-2.912h-0.05c-2.787 0-4.555 1.816-4.555 4.231 0 1.219 0.175 1.941 0.548 2.687h3.161c-0.548-0.945-0.797-1.518-0.797-2.314 0-0.845 0.548-1.568 1.493-1.568h0.05c0.821 0 1.12 0.25 2.788 1.692 2.762 2.39 3.832 2.912 5.824 2.912h0.048c2.739 0 4.555-1.917 4.555-4.305 0-1.195-0.298-2.215-0.722-3.086m-4.479-10.93h-12.344v3.011h12.643c1.567 0 2.189 0.548 2.189 1.319 0 0.772-0.622 1.32-2.189 1.32h-12.643v3.01h12.344c3.658 0 5.301-1.841 5.301-4.33 0-2.488-1.643-4.33-5.301-4.33m-9.641 53.817h12.114v-10.601h-12.114zm14.114 2h-16.114v-12.601h-2.685v-45.326h21.484v45.326h-2.685z"/>
|
||||
<path d="m692.79 947.02h2.827v2.319h-2.827z"/>
|
||||
<path d="m699.06 947.02h2.826v2.319h-2.826z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
1
docs/assets/stack.svg
Normal file
1
docs/assets/stack.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 84 KiB |
213
docs/boards.md
213
docs/boards.md
@ -1,213 +0,0 @@
|
||||
# Boards
|
||||
|
||||
The board support code is only used for self-contained examples and testing. It is not used when TinyUSB is part of a larger project. It is responsible for getting the MCU started and the USB peripheral clocked with minimal of on-board devices
|
||||
- One LED : for status
|
||||
- One Button : to get input from user
|
||||
- One UART : optional for device, but required for host examples
|
||||
|
||||
## Supported Boards
|
||||
|
||||
This code base already had supported for a handful of following boards (sorted alphabetically)
|
||||
|
||||
### Dialog DA146xx
|
||||
|
||||
- [DA14695 Development Kit – USB](https://www.dialog-semiconductor.com/products/da14695-development-kit-usb)
|
||||
- [DA1469x Development Kit – Pro](https://www.dialog-semiconductor.com/products/da14695-development-kit-pro)
|
||||
|
||||
### Espressif ESP32-S2
|
||||
|
||||
- Adafruit Feather ESP32-S2
|
||||
- [Adafruit Magtag 2.9" E-Ink WiFi Display](https://www.adafruit.com/product/4800)
|
||||
- [Adafruit Metro ESP32-S2](https://www.adafruit.com/product/4775)
|
||||
- [ESP32-S2-Kaluga-1](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html)
|
||||
- [ESP32-S2-Saola-1](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html)
|
||||
|
||||
### MicroChip SAMD11 & SAMD21
|
||||
|
||||
- [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||
- [Adafruit Feather M0 Express](https://www.adafruit.com/product/3403)
|
||||
- [Adafruit ItsyBitsy M0 Express](https://www.adafruit.com/product/3727)
|
||||
- [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505)
|
||||
- [Great Scott Gadgets LUNA](https://greatscottgadgets.com/luna/)
|
||||
- [Microchip SAMD11 Xplained Pro](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro)
|
||||
- [Microchip SAMD21 Xplained Pro](https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMD21-XPRO)
|
||||
- [Seeeduino Xiao](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||
|
||||
### MicroChip SAMD51 & SAME54
|
||||
|
||||
- [Adafruit Feather M4 Express](https://www.adafruit.com/product/3857)
|
||||
- [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800)
|
||||
- [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
||||
- [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||
- [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382)
|
||||
- [D5035-01](https://github.com/RudolphRiedel/USB_CAN-FD)
|
||||
- [Microchip SAME54 Xplained Pro](https://www.microchip.com/developmenttools/productdetails/atsame54-xpro)
|
||||
|
||||
### MicroChip SAMG
|
||||
|
||||
- [Microchip SAMG55 Xplained Pro](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO)
|
||||
|
||||
### MicroChip SAML22
|
||||
|
||||
- [SAML22 Feather](https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather)
|
||||
- [Sensor Watch](https://github.com/joeycastillo/Sensor-Watch)
|
||||
|
||||
### Nordic nRF5x
|
||||
|
||||
- [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||
- [Adafruit CLUE](https://www.adafruit.com/product/4500)
|
||||
- [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
|
||||
- [Adafruit Feather nRF52840 Sense](https://www.adafruit.com/product/4516)
|
||||
- [Adafruit ItsyBitsy nRF52840 Express](https://www.adafruit.com/product/4481)
|
||||
- [Arduino Nano 33 BLE](https://store.arduino.cc/usa/nano-33-ble)
|
||||
- [Arduino Nano 33 BLE Sense](https://store.arduino.cc/usa/nano-33-ble-sense)
|
||||
- [Maker Diary nRF52840 MDK Dongle](https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle)
|
||||
- [Nordic nRF52840 Development Kit (aka pca10056)](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
|
||||
- [Nordic nRF52840 Dongle (aka pca10059)](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle)
|
||||
- [Nordic nRF52833 Development Kit (aka pca10100)](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK)
|
||||
- [Raytac MDBT50Q-RX Dongle](https://www.raytac.com/product/ins.php?index_id=89)
|
||||
|
||||
### Nuvoton
|
||||
|
||||
- NuTiny SDK NUC120
|
||||
- [NuTiny NUC121S](https://direct.nuvoton.com/en/nutiny-nuc121s)
|
||||
- [NuTiny NUC125S](https://direct.nuvoton.com/en/nutiny-nuc125s)
|
||||
- [NuTiny NUC126V](https://direct.nuvoton.com/en/nutiny-nuc126v)
|
||||
- [NuTiny SDK NUC505Y](https://direct.nuvoton.com/en/nutiny-nuc505y)
|
||||
|
||||
### NXP iMX RT
|
||||
|
||||
- [MIMX RT1010 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1010-evaluation-kit:MIMXRT1010-EVK)
|
||||
- [MIMX RT1015 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1015-evaluation-kit:MIMXRT1015-EVK)
|
||||
- [MIMX RT1020 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1020-evaluation-kit:MIMXRT1020-EVK)
|
||||
- [MIMX RT1050 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1050-evaluation-kit:MIMXRT1050-EVK)
|
||||
- [MIMX RT1060 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1060-evk-i.mx-rt1060-evaluation-kit:MIMXRT1060-EVK)
|
||||
- [MIMX RT1064 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1064-evk-i.mx-rt1064-evaluation-kit:MIMXRT1064-EVK)
|
||||
- [Teensy 4.0 Development Board](https://www.pjrc.com/store/teensy40.html)
|
||||
|
||||
### NXP Kinetis
|
||||
|
||||
- [FRDM-KL25Z](https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z)
|
||||
|
||||
### NXP LPC 11-13-15
|
||||
|
||||
- [LPCXpresso 11u37](https://www.nxp.com/design/microcontrollers-developer-resources/lpcxpresso-boards/lpcxpresso-board-for-lpc11u37h:OM13074)
|
||||
- [LPCXpresso 11u68](https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc11u68:OM13058)
|
||||
- [LPCXpresso 1347](https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc1347:OM13045)
|
||||
- [LPCXpresso 1549](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1500-cortex-m3/lpcxpresso-board-for-lpc1549:OM13056)
|
||||
|
||||
### NXP LPC 17-40
|
||||
|
||||
- [ARM mbed LPC1768](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/arm-mbed-lpc1768-board:OM11043)
|
||||
- [Embedded Artists LPC4088 Quick Start board](https://www.embeddedartists.com/products/lpc4088-quickstart-board)
|
||||
- [LPCXpresso 1769](https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc1769:OM13000)
|
||||
|
||||
### NXP LPC 18-43
|
||||
|
||||
- [Embedded Artists LPC4357 Developer Kit](http://www.embeddedartists.com/products/kits/lpc4357_kit.php)
|
||||
- [Keil MCB1800 Evaluation Board](http://www.keil.com/mcb1800)
|
||||
- [LPCXpresso18S37 Development Board](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc4000-cortex-m4/lpcxpresso18s37-development-board:OM13076)
|
||||
- [NGX LPC4330-Xplorer](https://www.nxp.com/design/designs/lpc4330-xplorer-board:OM13027)
|
||||
|
||||
### NXP LPC 51
|
||||
- [LPCXpresso 51U68](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpcxpresso51u68-for-the-lpc51u68-mcus:OM40005)
|
||||
|
||||
### NXP LPC 54
|
||||
|
||||
- [LPCXpresso 54114](https://www.nxp.com/design/microcontrollers-developer-resources/lpcxpresso-boards/lpcxpresso54114-board:OM13089)
|
||||
|
||||
## NXP LPC55
|
||||
|
||||
- [Double M33 Express](https://www.crowdsupply.com/steiert-solutions/double-m33-express)
|
||||
- [LPCXpresso 55s28 EVK](https://www.nxp.com/design/software/development-software/lpcxpresso55s28-development-board:LPC55S28-EVK)
|
||||
- [LPCXpresso 55s69 EVK](https://www.nxp.com/design/development-boards/lpcxpresso-boards/lpcxpresso55s69-development-board:LPC55S69-EVK)
|
||||
- [MCU-Link](https://www.nxp.com/design/development-boards/lpcxpresso-boards/mcu-link-debug-probe:MCU-LINK)
|
||||
|
||||
### Renesas RX
|
||||
|
||||
- [GR-CITRUS](https://www.renesas.com/us/en/products/gadget-renesas/boards/gr-citrus)
|
||||
|
||||
### Raspberry Pi RP2040
|
||||
|
||||
- [Adafruit Feather RP2040](https://www.adafruit.com/product/4884)
|
||||
- [Adafruit ItsyBitsy RP2040](https://www.adafruit.com/product/4888)
|
||||
- [Adafruit QT Py RP2040](https://www.adafruit.com/product/4900)
|
||||
- [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)
|
||||
|
||||
### Silabs
|
||||
|
||||
- [EFM32GG12 Thunderboard Kit (SLTB009A)](https://www.silabs.com/development-tools/thunderboard/thunderboard-gg12-kit)
|
||||
|
||||
### Sony
|
||||
|
||||
- [Sony Spresense CXD5602](https://developer.sony.com/develop/spresense)
|
||||
|
||||
### ST STM32
|
||||
|
||||
- [Adafruit Feather STM32F405](https://www.adafruit.com/product/4382)
|
||||
- [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1)
|
||||
- [STLink-V3 Mini](https://www.st.com/en/development-tools/stlink-v3mini.html)
|
||||
- [STM32 L035c8 Discovery](https://www.st.com/en/evaluation-tools/32l0538discovery.html)
|
||||
- [STM32 L4R5zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html)
|
||||
- [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html)
|
||||
- [STM32 F072 Evaluation](https://www.st.com/en/evaluation-tools/stm32072b-eval.html)
|
||||
- [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html)
|
||||
- STM32 F103c Blue Pill
|
||||
- [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html)
|
||||
- [STM32 F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html)
|
||||
- STM32 F401cc Black Pill
|
||||
- [STM32 F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html)
|
||||
- [STM32 F411ce Black Pill](https://www.adafruit.com/product/4877)
|
||||
- [STM32 F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html)
|
||||
- [STM32 F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html)
|
||||
- [STM32 F723e Discovery](https://www.st.com/en/evaluation-tools/32f723ediscovery.html)
|
||||
- [STM32 F746zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f746zg.html)
|
||||
- [STM32 F746g Discovery](https://www.st.com/en/evaluation-tools/32f746gdiscovery.html)
|
||||
- [STM32 F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html)
|
||||
- [STM32 F769i Discovery](https://www.st.com/en/evaluation-tools/32f769idiscovery.html)
|
||||
- [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html)
|
||||
- [STM32 H743i Evaluation](https://www.st.com/en/evaluation-tools/stm32h743i-eval.html)
|
||||
- [STM32 H745i Discovery](https://www.st.com/en/evaluation-tools/stm32h745i-disco.html)
|
||||
|
||||
### TI
|
||||
|
||||
- [MSP430F5529 USB LaunchPad Evaluation Kit](http://www.ti.com/tool/MSP-EXP430F5529LP)
|
||||
|
||||
### Tomu
|
||||
|
||||
- [Fomu](https://www.crowdsupply.com/sutajio-kosagi/fomu)
|
||||
|
||||
## Add your own board
|
||||
|
||||
If you don't possess any of supported board above. Don't worry you can easily implemented your own one by following this guide as long as the mcu is supported.
|
||||
|
||||
- Create new makefile for your board at `hw/bsp/<board name>/board.mk` and linker file as well if needed.
|
||||
- Create new source file for your board at `hw/bsp/<board name>/<board name>.c` and implement following APIs
|
||||
|
||||
### Board APIs
|
||||
|
||||
#### board_init()
|
||||
|
||||
Is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED and button pins.
|
||||
One useful clock debugging technique is to set up a PWM output at a known value such as 500hz based on the USB clock so that you can verify it is correct with a logic probe or oscilloscope.
|
||||
Setup your USB in a crystal-less mode when available. That makes the code easier to port across boards.
|
||||
|
||||
#### board_led_write()
|
||||
|
||||
Set the pin corresponding to the led to output a value that lights the LED when `state` is true.
|
||||
|
||||
#### board_button_read()
|
||||
|
||||
Return current state of button, a `1` means active (pressed), a `0` means inactive.
|
||||
|
||||
#### board_millis()
|
||||
|
||||
The function returns the elapsed number of milliseconds since startup. On ARM this is commonly done with SysTick or Timer. This provide examples a way to measure time to blink LED or delay properly. It is only required when run examples without RTOS `CFG_TUSB_OS == OPT_OS_NONE`.
|
||||
|
||||
#### board_uart_read()
|
||||
|
||||
Get characters from UART peripheral.
|
||||
|
||||
#### board_uart_write()
|
||||
|
||||
Send characters to UART peripheral.
|
42
docs/conf.py
Normal file
42
docs/conf.py
Normal file
@ -0,0 +1,42 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'TinyUSB'
|
||||
copyright = '2021, Ha Thach'
|
||||
author = 'Ha Thach'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx_autodoc_typehints',
|
||||
'sphinxemoji.sphinxemoji',
|
||||
]
|
||||
|
||||
templates_path = ['_templates']
|
||||
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
html_theme = 'furo'
|
||||
html_title = 'TinyUSB'
|
||||
html_logo = 'assets/logo.svg'
|
||||
html_favicon = 'assets/logo.svg'
|
||||
html_theme_options = {
|
||||
'sidebar_hide_name': True,
|
||||
}
|
||||
|
||||
todo_include_todos = True
|
1
docs/contributing/code_of_conduct.rst
Symbolic link
1
docs/contributing/code_of_conduct.rst
Symbolic link
@ -0,0 +1 @@
|
||||
../../CODE_OF_CONDUCT.rst
|
23
docs/contributing/index.rst
Normal file
23
docs/contributing/index.rst
Normal file
@ -0,0 +1,23 @@
|
||||
************
|
||||
Contributing
|
||||
************
|
||||
|
||||
Contributing can be highly rewarding, but it can also be frustrating at times.
|
||||
It takes time to review patches, and as this is an open source project, that
|
||||
sometimes can take a while. The reviewing process depends on the availability
|
||||
of the maintainers, who may not be always available. Please try to be
|
||||
understanding throught the process.
|
||||
|
||||
There a few guidelines you need to keep in mind when contributing. Please have
|
||||
a look at them as that will make the contribution process easier for all
|
||||
parties.
|
||||
|
||||
Index
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
code_of_conduct
|
||||
structure
|
||||
porting
|
@ -1,4 +1,7 @@
|
||||
# Porting
|
||||
|
||||
*******
|
||||
Porting
|
||||
*******
|
||||
|
||||
TinyUSB is designed to be a universal USB protocol stack for microcontrollers. It
|
||||
handles most of the high level USB protocol and relies on the microcontroller's USB peripheral for
|
||||
@ -8,129 +11,165 @@ for the microcontroller to other projects, especially those already using TinyUS
|
||||
|
||||
Below are instructions on how to get the cdc_msc device example running on a new microcontroller. Doing so includes adding the common code necessary for other uses while minimizing other extra code. Whenever you see a phrase or word in <> it should be replaced.
|
||||
|
||||
## Register defs
|
||||
Register defs
|
||||
-------------
|
||||
|
||||
The first step to adding support is including the register definitions and startup code for the
|
||||
microcontroller in TinyUSB. We write the TinyUSB implementation against these structs instead of higher level functions to keep the code small and to prevent function name collisions in linking of larger projects. For ARM microcontrollers this is the CMSIS definitions. They should be
|
||||
placed in the `hw/mcu/<vendor>/<chip_family>` directory.
|
||||
placed in the ``hw/mcu/<vendor>/<chip_family>`` directory.
|
||||
|
||||
Once this is done, create a directory in `hw/bsp/<your board name>` for the specific board you are using to test the code. (Duplicating an existing board's directory is the best way to get started.) The board should be a readily available development board so that others can also test.
|
||||
Once this is done, create a directory in ``hw/bsp/<your board name>`` for the specific board you are using to test the code. (Duplicating an existing board's directory is the best way to get started.) The board should be a readily available development board so that others can also test.
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
## Build
|
||||
Now that those directories are in place, we can start our iteration process to get the example building successfully. To build, run from the root of TinyUSB:
|
||||
|
||||
`make -C examples/device/cdc_msc BOARD=<board>`
|
||||
``make -C examples/device/cdc_msc BOARD=<board>``
|
||||
|
||||
Unless, you've read ahead, this will fail miserably. Now, lets get it to fail less by updating the files in the board directory. The code in the board's directory is responsible for setting up the microcontroller's clocks and pins so that USB works. TinyUSB itself only operates on the USB peripheral. The board directory also includes information what files are needed to build the example.
|
||||
|
||||
One of the first things to change is the `-DCFG_TUSB_MCU` cflag in the `board.mk` file. This is used to tell TinyUSB what platform is being built. So, add an entry to `src/tusb_option.h` and update the CFLAG to match.
|
||||
One of the first things to change is the ``-DCFG_TUSB_MCU`` cflag in the ``board.mk`` file. This is used to tell TinyUSB what platform is being built. So, add an entry to ``src/tusb_option.h`` and update the CFLAG to match.
|
||||
|
||||
Update `board.mk`'s VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from `src/portable` into `src/portable/<vendor>/<chip_family>` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling.
|
||||
Update ``board.mk``\ 's VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from ``src/portable`` into ``src/portable/<vendor>/<chip_family>`` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling.
|
||||
|
||||
## Implementation
|
||||
At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the `board.mk` to include specific CFLAGS, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo.
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the ``board.mk`` to include specific CFLAGS, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo.
|
||||
|
||||
Board Support (BSP)
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
### Board Support (BSP)
|
||||
The board support code is only used for self-contained examples and testing. It is not used when TinyUSB is part of a larger project. Its responsible for getting the MCU started and the USB peripheral clocked. It also optionally provides LED definitions that are used to blink an LED to show that the code is running.
|
||||
|
||||
It is located in `hw/bsp/<board name>/board_<board name>.c`.
|
||||
It is located in ``hw/bsp/<board name>/board_<board name>.c``.
|
||||
|
||||
#### board_init
|
||||
`board_init` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins.
|
||||
board_init
|
||||
~~~~~~~~~~
|
||||
|
||||
``board_init`` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins.
|
||||
|
||||
One useful clock debugging technique is to set up a PWM output at a known value such as 500hz based on the USB clock so that you can verify it is correct with a logic probe or oscilloscope.
|
||||
|
||||
Setup your USB in a crystal-less mode when available. That makes the code easier to port across boards.
|
||||
|
||||
#### board_led_write
|
||||
Feel free to skip this until you want to verify your demo code is running. To implement, set the pin corresponding to the led to output a value that lights the LED when `state` is true.
|
||||
board_led_write
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
### OS Abstraction Layer (OSAL)
|
||||
Feel free to skip this until you want to verify your demo code is running. To implement, set the pin corresponding to the led to output a value that lights the LED when ``state`` is true.
|
||||
|
||||
OS Abstraction Layer (OSAL)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The OS Abstraction Layer is responsible for providing basic data structures for TinyUSB that may allow for concurrency when used with an RTOS. Without an RTOS it simply handles concurrency issues between the main code and interrupts.
|
||||
|
||||
The code is almost entirely agnostic of MCU and lives in `src/osal`.
|
||||
The code is almost entirely agnostic of MCU and lives in ``src/osal``.
|
||||
|
||||
### Device API
|
||||
Device API
|
||||
^^^^^^^^^^
|
||||
|
||||
After the USB device is setup, the USB device code works by processing events on the main thread (by calling `tud_task`). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing.
|
||||
After the USB device is setup, the USB device code works by processing events on the main thread (by calling ``tud_task``\ ). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing.
|
||||
|
||||
All of the code for the low-level device API is in `src/portable/<vendor>/<chip family>/dcd_<chip family>.c`.
|
||||
All of the code for the low-level device API is in ``src/portable/<vendor>/<chip family>/dcd_<chip family>.c``.
|
||||
|
||||
#### Device Setup
|
||||
Device Setup
|
||||
~~~~~~~~~~~~
|
||||
|
||||
##### dcd_init
|
||||
dcd_init
|
||||
""""""""
|
||||
|
||||
Initializes the USB peripheral for device mode and enables it.
|
||||
This function should enable internal D+/D- pull-up for enumeration.
|
||||
|
||||
##### dcd_int_enable / dcd_int_disable
|
||||
dcd_int_enable / dcd_int_disable
|
||||
""""""""""""""""""""""""""""""""
|
||||
|
||||
Enables or disables the USB device interrupt(s). May be used to prevent concurrency issues when mutating data structures shared between main code and the interrupt handler.
|
||||
|
||||
##### dcd_int_handler
|
||||
dcd_int_handler
|
||||
"""""""""""""""
|
||||
|
||||
Processes all the hardware generated events e.g Bus reset, new data packet from host etc ... It will be called by application in the MCU USB interrupt handler.
|
||||
|
||||
##### dcd_set_address
|
||||
dcd_set_address
|
||||
"""""""""""""""
|
||||
|
||||
Called when the device is given a new bus address.
|
||||
|
||||
If your peripheral automatically changes address during enumeration (like the nrf52) you may leave this empty and also no queue an event for the corresponding SETUP packet.
|
||||
|
||||
##### dcd_remote_wakeup
|
||||
dcd_remote_wakeup
|
||||
"""""""""""""""""
|
||||
|
||||
Called to remote wake up host when suspended (e.g hid keyboard)
|
||||
|
||||
##### dcd_connect / dcd_disconnect
|
||||
dcd_connect / dcd_disconnect
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
Connect or disconnect the data-line pull-up resistor. Define only if MCU has an internal pull-up. (BSP may define for MCU without internal pull-up.)
|
||||
|
||||
#### Special events
|
||||
Special events
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
You must let TinyUSB know when certain events occur so that it can continue its work. There are a few methods you can call to queue events for TinyUSB to process.
|
||||
|
||||
##### dcd_event_bus_signal
|
||||
dcd_event_bus_signal
|
||||
""""""""""""""""""""
|
||||
|
||||
There are a number of events that your peripheral may communicate about the state of the bus. Here is an overview of what they are. Events in **BOLD** must be provided for TinyUSB to work.
|
||||
|
||||
|
||||
* **DCD_EVENT_RESET** - Triggered when the host resets the bus causing the peripheral to reset. Do any other internal reset you need from the interrupt handler such as resetting the control endpoint.
|
||||
* DCD_EVENT_SOF - Signals the start of a new USB frame.
|
||||
|
||||
Calls to this look like:
|
||||
|
||||
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
|
||||
.. code-block::
|
||||
|
||||
The first `0` is the USB peripheral number. Statically saying 0 is common for single USB device MCUs.
|
||||
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
|
||||
|
||||
The `true` indicates the call is from an interrupt handler and will always be the case when porting in this way.
|
||||
|
||||
##### dcd_setup_received
|
||||
The first ``0`` is the USB peripheral number. Statically saying 0 is common for single USB device MCUs.
|
||||
|
||||
SETUP packets are a special type of transaction that can occur at any time on the control endpoint, numbered `0`. Since they are unique, most peripherals have special handling for them. Their data is always 8 bytes in length as well.
|
||||
The ``true`` indicates the call is from an interrupt handler and will always be the case when porting in this way.
|
||||
|
||||
dcd_setup_received
|
||||
""""""""""""""""""
|
||||
|
||||
SETUP packets are a special type of transaction that can occur at any time on the control endpoint, numbered ``0``. Since they are unique, most peripherals have special handling for them. Their data is always 8 bytes in length as well.
|
||||
|
||||
Calls to this look like:
|
||||
|
||||
dcd_event_setup_received(0, setup, true);
|
||||
.. code-block::
|
||||
|
||||
As before with `dcd_event_bus_signal` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue.
|
||||
dcd_event_setup_received(0, setup, true);
|
||||
|
||||
#### Endpoints
|
||||
|
||||
As before with ``dcd_event_bus_signal`` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue.
|
||||
|
||||
Endpoints
|
||||
~~~~~~~~~
|
||||
|
||||
Endpoints are the core of the USB data transfer process. They come in a few forms such as control, isochronous, bulk, and interrupt. We won't cover the details here except with some caveats in open below. In general, data is transferred by setting up a buffer of a given length to be transferred on a given endpoint address and then waiting for an interrupt to signal that the transfer is finished. Further details below.
|
||||
|
||||
Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides `tu_edpt_number` and `tu_edpt_dir` to unpack this data from the address. Here is a snippet that does it.
|
||||
Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides ``tu_edpt_number`` and ``tu_edpt_dir`` to unpack this data from the address. Here is a snippet that does it.
|
||||
|
||||
uint8_t epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t dir = tu_edpt_dir(ep_addr);
|
||||
.. code-block::
|
||||
|
||||
##### dcd_edpt_open
|
||||
uint8_t epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
|
||||
dcd_edpt_open
|
||||
"""""""""""""
|
||||
|
||||
Opening an endpoint is done for all non-control endpoints once the host picks a configuration that the device should use. At this point, the endpoint should be enabled in the peripheral and configured to match the endpoint descriptor. Pay special attention to the direction of the endpoint you can get from the helper methods above. It will likely change what registers you are setting.
|
||||
|
||||
Also make sure to enable endpoint specific interrupts.
|
||||
|
||||
##### dcd_edpt_close
|
||||
dcd_edpt_close
|
||||
""""""""""""""
|
||||
|
||||
Close an endpoint. his function is used for implementing alternate settings.
|
||||
|
||||
@ -138,16 +177,17 @@ After calling this, the device should not respond to any packets directed toward
|
||||
|
||||
Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call.
|
||||
|
||||
##### dcd_edpt_xfer
|
||||
dcd_edpt_xfer
|
||||
"""""""""""""
|
||||
|
||||
`dcd_edpt_xfer` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral.
|
||||
``dcd_edpt_xfer`` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral.
|
||||
|
||||
Besides that, all other transactions are relatively straight-forward. The endpoint address provides the endpoint
|
||||
number and direction which usually determines where to write the buffer info. The buffer and its length are usually
|
||||
written to a specific location in memory and the peripheral is told the data is valid. (Maybe by writing a 1 to a
|
||||
register or setting a counter register to 0 for OUT or length for IN.)
|
||||
|
||||
The transmit buffer alignment is determined by `CFG_TUSB_MEM_ALIGN`.
|
||||
The transmit buffer alignment is determined by ``CFG_TUSB_MEM_ALIGN``.
|
||||
|
||||
One potential pitfall is that the buffer may be longer than the maximum endpoint size of one USB
|
||||
packet. Some peripherals can handle transmitting multiple USB packets for a provided buffer (like the SAMD21).
|
||||
@ -155,37 +195,47 @@ Others (like the nRF52) may need each USB packet queued individually. To make th
|
||||
some state for yourself and queue up an intermediate USB packet from the interrupt handler.
|
||||
|
||||
Once the transaction is going, the interrupt handler will notify TinyUSB of transfer completion.
|
||||
During transmission, the IN data buffer is guarenteed to remain unchanged in memory until the `dcd_xfer_complete` function is called.
|
||||
During transmission, the IN data buffer is guarenteed to remain unchanged in memory until the ``dcd_xfer_complete`` function is called.
|
||||
|
||||
The dcd_edpt_xfer function must never add zero-length-packets (ZLP) on its own to a transfer. If a ZLP is required,
|
||||
then it must be explicitly sent by the stack calling dcd_edpt_xfer(), by calling dcd_edpt_xfer() a second time with len=0.
|
||||
For control transfers, this is automatically done in `usbd_control.c`.
|
||||
For control transfers, this is automatically done in ``usbd_control.c``.
|
||||
|
||||
At the moment, only a single buffer can be transmitted at once. There is no provision for double-buffering. new dcd_edpt_xfer() will not
|
||||
be called again on the same endpoint address until the driver calls dcd_xfer_complete() (except in cases of USB resets).
|
||||
|
||||
##### dcd_xfer_complete
|
||||
dcd_xfer_complete
|
||||
"""""""""""""""""
|
||||
|
||||
Once a transfer completes you must call dcd_xfer_complete from the USB interrupt handler to let TinyUSB know that a transaction has completed. Here is a sample call:
|
||||
|
||||
dcd_event_xfer_complete(0, ep_addr, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
||||
.. code-block::
|
||||
|
||||
dcd_event_xfer_complete(0, ep_addr, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
|
||||
The arguments are:
|
||||
|
||||
|
||||
* the USB peripheral number
|
||||
* the endpoint address
|
||||
* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in `dcd_edpt_xfer`)
|
||||
* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in ``dcd_edpt_xfer``\ )
|
||||
* the result of the transfer. Failure isn't handled yet.
|
||||
* `true` to note the call is from an interrupt handler.
|
||||
* ``true`` to note the call is from an interrupt handler.
|
||||
|
||||
##### dcd_edpt_stall / dcd_edpt_clear_stall
|
||||
dcd_edpt_stall / dcd_edpt_clear_stall
|
||||
"""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of `dcd_edpt_stall`, `dcd_edpt_clear_stall` help manage the stall state of all endpoints.
|
||||
Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of ``dcd_edpt_stall``\ , ``dcd_edpt_clear_stall`` help manage the stall state of all endpoints.
|
||||
|
||||
## Woohoo!
|
||||
Woohoo!
|
||||
-------
|
||||
|
||||
At this point you should have everything working! ;-) Of course, you may not write perfect code. Here are some tips and tricks for debugging.
|
||||
|
||||
Use [WireShark](https://www.wireshark.org/) or [a Beagle](https://www.totalphase.com/protocols/usb/) to sniff the USB traffic. When things aren't working its likely very early in the USB enumeration process. Figuring out where can help clue in where the issue is. For example:
|
||||
Use `WireShark <https://www.wireshark.org/>`_ or `a Beagle <https://www.totalphase.com/protocols/usb/>`_ to sniff the USB traffic. When things aren't working its likely very early in the USB enumeration process. Figuring out where can help clue in where the issue is. For example:
|
||||
|
||||
|
||||
* If the host sends a SETUP packet and its not ACKed then your USB peripheral probably isn't started correctly.
|
||||
* If the peripheral is started correctly but it still didn't work, then verify your usb clock is correct. (You did output a PWM based on it right? ;-) )
|
||||
* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example `tud_task` may not be called.) If thats OK, the `dcd_xfer_complete` may not be setting up the next transaction correctly.
|
||||
* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example ``tud_task`` may not be called.) If thats OK, the ``dcd_xfer_complete`` may not be setting up the next transaction correctly.
|
59
docs/contributing/structure.rst
Normal file
59
docs/contributing/structure.rst
Normal file
@ -0,0 +1,59 @@
|
||||
*********
|
||||
Structure
|
||||
*********
|
||||
|
||||
Tree
|
||||
====
|
||||
|
||||
::
|
||||
|
||||
.
|
||||
├── docs
|
||||
├── examples
|
||||
├── hw
|
||||
│ ├── bsp
|
||||
│ └── mcu
|
||||
├── lib
|
||||
├── src
|
||||
├── test
|
||||
└── tools
|
||||
|
||||
docs
|
||||
----
|
||||
|
||||
Documentation
|
||||
|
||||
examples
|
||||
--------
|
||||
|
||||
Sample with Makefile build support
|
||||
|
||||
hw/bsp
|
||||
------
|
||||
|
||||
Supported boards source files
|
||||
|
||||
hw/mcu
|
||||
------
|
||||
|
||||
Low level mcu core & peripheral drivers
|
||||
|
||||
lib
|
||||
---
|
||||
|
||||
Sources from 3rd party such as freeRTOS, fatfs ...
|
||||
|
||||
src
|
||||
---
|
||||
|
||||
All sources files for TinyUSB stack itself.
|
||||
|
||||
test
|
||||
----
|
||||
|
||||
Unit tests for the stack
|
||||
|
||||
tools
|
||||
-----
|
||||
|
||||
Files used internally
|
@ -1,137 +0,0 @@
|
||||
# Getting Started #
|
||||
|
||||
## Add TinyUSB to your project
|
||||
|
||||
It is relatively simple to incorporate tinyusb to your (existing) project
|
||||
|
||||
- Copy or `git submodule` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb*
|
||||
- Add all the .c in the `tinyusb/src` folder to your project
|
||||
- Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h.
|
||||
- Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards).
|
||||
- If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud_descriptor_** callbacks for the stack to work.
|
||||
- Add tusb_init() call to your reset initialization code.
|
||||
- Call `tud_int_handler()` (device) and/or `tuh_int_handler()` (host) in your USB IRQ Handler
|
||||
- Implement all enabled classes's callbacks.
|
||||
- If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner.
|
||||
|
||||
~~~{.c}
|
||||
int main(void)
|
||||
{
|
||||
your_init_code();
|
||||
tusb_init(); // initialize tinyusb stack
|
||||
|
||||
while(1) // the mainloop
|
||||
{
|
||||
your_application_code();
|
||||
|
||||
tud_task(); // device task
|
||||
tuh_task(); // host task
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
## Examples
|
||||
|
||||
For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of [the supported Boards](boards.md). Firstly we need to `git clone` if not already
|
||||
|
||||
```
|
||||
$ git clone https://github.com/hathach/tinyusb tinyusb
|
||||
$ cd tinyusb
|
||||
```
|
||||
|
||||
Some TinyUSB examples also requires external submodule libraries in `/lib` such as FreeRTOS, Lightweight IP to build. Run following command to fetch them
|
||||
|
||||
```
|
||||
$ git submodule update --init lib
|
||||
```
|
||||
|
||||
In addition, MCU driver submodule is also needed to provide low-level MCU peripheral's driver. Luckily, it will be fetched if needed when you run the `make` to build your board.
|
||||
|
||||
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy `/examples/device/99-tinyusb.rules` file to /etc/udev/rules.d/ then run `sudo udevadm control --reload-rules && sudo udevadm trigger` is good enough.
|
||||
|
||||
### Build
|
||||
|
||||
To build example, first change directory to an example folder.
|
||||
|
||||
```
|
||||
$ cd examples/device/cdc_msc
|
||||
```
|
||||
|
||||
Then compile with `make BOARD=[board_name] all`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all
|
||||
```
|
||||
|
||||
Note: `BOARD` can be found as directory name in `hw/bsp`, either in its family/boards or directly under bsp (no family).
|
||||
|
||||
#### Port Selection
|
||||
|
||||
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option `PORT=x` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco PORT=1 all
|
||||
```
|
||||
|
||||
#### Port Speed
|
||||
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option `SPEED=full/high` e.g To force F723 operate at full instead of default high speed
|
||||
|
||||
```
|
||||
$ make BOARD=stm32f746disco SPEED=full all
|
||||
```
|
||||
|
||||
### Debug
|
||||
|
||||
To compile for debugging add `DEBUG=1`, for example
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express DEBUG=1 all
|
||||
```
|
||||
|
||||
#### Log
|
||||
|
||||
Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional `LOG=`. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 all
|
||||
```
|
||||
|
||||
#### Logger
|
||||
|
||||
By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols:
|
||||
|
||||
- `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/)
|
||||
- Cons: requires jlink as the debugger.
|
||||
- Pros: work with most if not all MCUs
|
||||
- Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package.
|
||||
- `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header.
|
||||
- Cons: only work with ARM Cortex MCUs minus M0
|
||||
- Pros: should be compatible with more debugger that support SWO.
|
||||
- Software viewer should be provided along with your debugger driver.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
|
||||
```
|
||||
|
||||
### Flash
|
||||
|
||||
`flash` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash
|
||||
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
|
||||
```
|
||||
|
||||
Since jlink can be used with most of the boards, there is also `flash-jlink` target for your convenience.
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express flash-jlink
|
||||
```
|
||||
|
||||
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with `uf2` target
|
||||
|
||||
```
|
||||
$ make BOARD=feather_nrf52840_express all uf2
|
||||
```
|
25
docs/index.rst
Normal file
25
docs/index.rst
Normal file
@ -0,0 +1,25 @@
|
||||
:hide-toc:
|
||||
|
||||
*********
|
||||
TinyUSB
|
||||
*********
|
||||
|
||||
TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems,
|
||||
designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events being deferred and then handled in the non-ISR task function.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:caption: Index
|
||||
:hidden:
|
||||
|
||||
Info <info/index>
|
||||
Reference <reference/index>
|
||||
Contributing <contributing/index>
|
||||
|
||||
.. toctree::
|
||||
:caption: External Links
|
||||
:hidden:
|
||||
|
||||
Source Code <https://github.com/hathach/tinyusb>
|
||||
Issue Tracker <https://github.com/hathach/tinyusb/issues>
|
||||
Discussions <https://github.com/hathach/tinyusb/discussions>
|
@ -1,10 +1,115 @@
|
||||
# TinyUSB Changelog
|
||||
*********
|
||||
Changelog
|
||||
*********
|
||||
|
||||
## 0.10.1 - 2021.06.03
|
||||
0.11.0 (2021-08-29)
|
||||
===================
|
||||
|
||||
- Add host/hid_controller example: only worked/tested with Sony PS4 DualShock controller
|
||||
- Add device/hid_boot_interface example
|
||||
- Add support for Renesas CCRX toolchain for RX mcu
|
||||
|
||||
Device Controller Driver (DCD)
|
||||
------------------------------
|
||||
|
||||
- Add new DCD port for SAMx7x (E70, S70, V70, V71)
|
||||
- Add new mcu K32L2Bxx
|
||||
- Add new mcu GD32VF103
|
||||
- Add new mcu STM32l151
|
||||
- Add new mcu SAML21
|
||||
- Add new mcu RX65n RX72n
|
||||
- Fix NUC120/121/126 USBRAM can only be accessed in byte manner. Also improve set_address & disable sof
|
||||
- Add Suspend/Resume handling for Renesas RX family.
|
||||
- Fix DA1469x no VBUS startup
|
||||
|
||||
Synopsys
|
||||
^^^^^^^^
|
||||
|
||||
- Fix Synopsys set address bug which could cause re-enumeration failed
|
||||
- Fix for dcd_synopsys driver integer overflow in HS mode (issue #968)
|
||||
|
||||
nRF5x
|
||||
^^^^^
|
||||
|
||||
- Add nRF5x suspend, resume and remote wakeup
|
||||
- Fix nRF5x race condition with TASKS_EP0RCVOUT
|
||||
|
||||
RP2040
|
||||
^^^^^^
|
||||
|
||||
- Add RP2040 suspend & resume support
|
||||
- Implement double buffer for both host and device (#891). Howver device EPOUT is still single bufferred due to techinical issue with short packet
|
||||
|
||||
Device Stack
|
||||
------------
|
||||
|
||||
USBD
|
||||
^^^^
|
||||
|
||||
- Better support big endian mcu
|
||||
- Add tuh_inited() and tud_inited(), will separte tusb_init/inited() to tud/tuh init/inited
|
||||
- Add dcd_attr.h for defining common controller attribute such as max endpoints
|
||||
|
||||
Bluetooth
|
||||
^^^^^^^^^
|
||||
|
||||
- Fix stridx error in descriptor template
|
||||
|
||||
DFU
|
||||
^^^
|
||||
|
||||
- Enhance DFU implementation to support multiple alternate interface and better support bwPollTimeout
|
||||
- Rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU
|
||||
|
||||
HID
|
||||
^^^
|
||||
|
||||
- Fix newline usage keyboard (ENTER 0x28)
|
||||
- Better support Hid Get/Set report
|
||||
- Change max gamepad support from 16 to 32 buttons
|
||||
|
||||
MIDI
|
||||
^^^^
|
||||
|
||||
- Fix midi available
|
||||
- Fix midi data
|
||||
- Fix an issue when calling midi API when not enumerated yet
|
||||
|
||||
UAC2
|
||||
^^^^
|
||||
|
||||
- Fix bug and enhance of UAC2
|
||||
|
||||
Vendor
|
||||
^^^^^^
|
||||
|
||||
- Fix vendor fifo deadlock in certain case
|
||||
- Add tud_vendor_n_read_flush
|
||||
|
||||
Host Controller Driver (HCD)
|
||||
----------------------------
|
||||
|
||||
RP2040
|
||||
^^^^^^
|
||||
|
||||
- Implement double bufferred to fix E4 errata and boost performance
|
||||
- Lots of rp2040 update and enhancment
|
||||
|
||||
Host Stack
|
||||
----------
|
||||
|
||||
- Major update and rework most of host stack, still needs more improvement
|
||||
- Lots of improvement and update in parsing configuration and control
|
||||
- Rework and major update to HID driver. Will default to enable boot interface if available
|
||||
- Sepearate CFG_TUH_DEVICE_MAX and CFG_TUH_HUB for better management and reduce SRAM usage
|
||||
|
||||
0.10.1 (2021-06-03)
|
||||
===================
|
||||
|
||||
- rework rp2040 examples and CMake build, allow better integration with pico-sdk
|
||||
|
||||
### Host Controller Driver (HCD)
|
||||
Host Controller Driver (HCD)
|
||||
----------------------------
|
||||
|
||||
- Fix rp2040 host driver: incorrect PID with low speed device with max packet size of 8 bytes
|
||||
- Improve hub driver
|
||||
@ -12,18 +117,20 @@
|
||||
- Use hcd_frame_number() instead of micro frame
|
||||
- Fix OHCI endpoint address and xferred_bytes in xfer complete event
|
||||
|
||||
## 0.10.0 - 2021.05.28
|
||||
0.10.0 (2021-05-28)
|
||||
===================
|
||||
|
||||
- Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode
|
||||
- Improve audio_test example and add audio_4_channel_mic example
|
||||
- Add new dfu example
|
||||
- Remove pico-sdk from submodule
|
||||
|
||||
### Device Controller Driver (DCD)
|
||||
Device Controller Driver (DCD)
|
||||
------------------------------
|
||||
|
||||
- Add new DCD port for Silabs EFM32GG12 with board Thunderboard Kit (SLTB009A)
|
||||
- Add new DCD port Renesas RX63N, board GR-CITRUS
|
||||
- Add new (optional) endpoint API dcd_edpt_xfer_fifo
|
||||
- Add new (optional) endpoint API dcd_edpt_xfer_fifo
|
||||
- Fix build with nRF5340
|
||||
- Fix build with lpc15 and lpc54
|
||||
- Fix build with lpc177x_8x
|
||||
@ -32,11 +139,13 @@
|
||||
- Add support for Espressif esp32s3
|
||||
- nRF: fix race condition that could cause drop packet of Bulk OUT transfer
|
||||
|
||||
### USB Device Driver (USBD)
|
||||
USB Device Driver (USBD)
|
||||
------------------------
|
||||
|
||||
- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo
|
||||
|
||||
### Device Class Driver
|
||||
Device Class Driver
|
||||
-------------------
|
||||
|
||||
CDC
|
||||
|
||||
@ -50,6 +159,7 @@ HID
|
||||
|
||||
- Fix keyboard report descriptor template
|
||||
- Add more hid keys constant from 0x6B to 0xA4
|
||||
|
||||
- [Breaking] rename API
|
||||
- HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE
|
||||
- tud_hid_boot_mode() to tud_hid_get_protocol()
|
||||
@ -58,29 +168,37 @@ HID
|
||||
MIDI
|
||||
|
||||
- Fix MIDI buffer overflow issue
|
||||
|
||||
- [Breaking] rename API
|
||||
- Rename tud_midi_read() to tud_midi_stream_read()
|
||||
- Rename tud_midi_write() to tud_midi_stream_write()
|
||||
- Rename tud_midi_receive() to tud_midi_packet_read()
|
||||
- Rename tud_midi_send() to tud_midi_packet_write()
|
||||
|
||||
### Host Controller Driver (HCD)
|
||||
Host Controller Driver (HCD)
|
||||
----------------------------
|
||||
|
||||
- No noticable changes
|
||||
|
||||
### USB Host Driver (USBH)
|
||||
USB Host Driver (USBH)
|
||||
----------------------
|
||||
|
||||
- No noticable changes
|
||||
|
||||
### Host Class Driver
|
||||
Host Class Driver
|
||||
-----------------
|
||||
|
||||
- HID: Rework host hid driver, basically everything changes
|
||||
|
||||
## 0.9.0 - 2021.03.12
|
||||
|
||||
### Device Stack
|
||||
0.9.0 (2021-03-12)
|
||||
==================
|
||||
|
||||
#### Device Controller Driver (DCD)
|
||||
Device Stack
|
||||
------------
|
||||
|
||||
Device Controller Driver (DCD)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
RP2040
|
||||
|
||||
@ -99,13 +217,15 @@ NXP Transdimention
|
||||
|
||||
- Update dcd_init() to reset controller to device mode
|
||||
|
||||
#### USB Device Driver (USBD)
|
||||
USB Device Driver (USBD)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Fix issue with status zlp (tud_control_status) is returned by class driver with SET/CLEAR_FEATURE for endpoint.
|
||||
- Correct endpoint size check for fullspeed bulk, can be 8, 16, 32, 64
|
||||
- Ack SET_INTERFACE even if it is not implemented by class driver.
|
||||
|
||||
#### Device Class Driver
|
||||
Device Class Driver
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
DFU Runtime
|
||||
|
||||
@ -114,20 +234,23 @@ DFU Runtime
|
||||
CDC
|
||||
|
||||
- Add tud_cdc_send_break_cb() to support break request
|
||||
- Improve CDC receive, minor behavior changes: when tud_cdc_rx_wanted_cb() is invoked wanted_char may not be the last byte in the fifo
|
||||
- Improve CDC receive, minor behavior changes: when tud_cdc_rx_wanted_cb() is invoked wanted_char may not be the last byte in the fifo
|
||||
|
||||
HID
|
||||
|
||||
- [Breaking] Add itf argument to hid API to support multiple instances, follow API has signature changes
|
||||
|
||||
- tud_hid_descriptor_report_cb()
|
||||
- tud_hid_get_report_cb()
|
||||
- tud_hid_set_report_cb()
|
||||
- tud_hid_boot_mode_cb()
|
||||
- tud_hid_set_idle_cb()
|
||||
|
||||
- Add report complete callback tud_hid_report_complete_cb() API
|
||||
- Add DPad/Hat support for HID Gamepad
|
||||
- TUD_HID_REPORT_DESC_GAMEPAD() now support 16 buttons, 2 joysticks, 1 hat/dpad
|
||||
- Add hid_gamepad_report_t along with GAMEPAD_BUTTON_ and GAMEPAD_HAT_ enum
|
||||
|
||||
- `TUD_HID_REPORT_DESC_GAMEPAD()` now support 16 buttons, 2 joysticks, 1 hat/dpad
|
||||
- Add hid_gamepad_report_t along with `GAMEPAD_BUTTON_` and `GAMEPAD_HAT_` enum
|
||||
- Add Gamepad to hid_composite / hid_composite_freertos example
|
||||
|
||||
MIDI
|
||||
@ -136,23 +259,30 @@ MIDI
|
||||
- Fix typo in tud_midi_write24(), make example less ambigous for cable and channel
|
||||
- Fix incorrect endpoint descriptor length, MIDI v1 use Audio v1 which has 9-byte endpoint descriptor (instead of 7)
|
||||
|
||||
### Host Stack
|
||||
Host Stack
|
||||
----------
|
||||
|
||||
#### Host Controller Driver (HCD)
|
||||
Host Controller Driver (HCD)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Add rhport to hcd_init()
|
||||
- Improve EHCI/OHCI driver abstraction
|
||||
|
||||
- Move echi/ohci files to portable/
|
||||
- Rename hcd_lpc18_43 to hcd_transdimension
|
||||
- Sub hcd API with hcd_ehci_init(), hcd_ehci_register_addr()
|
||||
|
||||
- Update NXP transdimention hcd_init() to reset controller to host mode
|
||||
|
||||
- Ported hcd to rt10xx
|
||||
|
||||
#### USB Host Driver (USBH)
|
||||
USB Host Driver (USBH)
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- No noticeable changes to usbh
|
||||
|
||||
#### Host Class Driver
|
||||
Host Class Driver
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
MSC
|
||||
|
||||
@ -164,7 +294,8 @@ MSC
|
||||
- Add tuh_msc_get_block_count(), tuh_msc_get_block_size()
|
||||
- Add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities
|
||||
|
||||
### Others
|
||||
Others
|
||||
------
|
||||
|
||||
- Add basic support for rt-thread OS
|
||||
- Change zero bitfield length to more explicit padding
|
||||
@ -177,25 +308,33 @@ MSC
|
||||
- LPCXpresso 55s28
|
||||
- LPCXpresso 18s37
|
||||
|
||||
## 0.8.0 - 2021.02.05
|
||||
|
||||
### Device Controller Driver
|
||||
0.8.0 (2021-02-05)
|
||||
==================
|
||||
|
||||
Device Controller Driver
|
||||
------------------------
|
||||
|
||||
- Added new device support for Raspberry Pi RP2040
|
||||
- Added new device support for NXP Kinetis KL25ZXX
|
||||
- Use dcd_event_bus_reset() with link speed to replace bus_signal
|
||||
|
||||
- ESP32-S2:
|
||||
- Add bus suspend and wakeup support
|
||||
|
||||
- SAMD21:
|
||||
- Fix (walkaround) samd21 setup_packet overflow by USB DMA
|
||||
|
||||
- STM32 Synopsys:
|
||||
- Rework USB FIFO allocation scheme and allow RX FIFO size reduction
|
||||
|
||||
- Sony CXD56
|
||||
- Update Update Spresense SDK to 2.0.2
|
||||
- Fix dcd issues with setup packets
|
||||
- Correct EP number for cdc_msc example
|
||||
|
||||
### USB Device
|
||||
USB Device
|
||||
----------
|
||||
|
||||
**USBD**
|
||||
|
||||
@ -207,26 +346,33 @@ MSC
|
||||
|
||||
- CDC
|
||||
- Allow to transmit data, even if the host does not support control line states i.e set DTR
|
||||
|
||||
- HID
|
||||
- change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64
|
||||
|
||||
- MIDI
|
||||
- Fix midi sysex sending bug
|
||||
|
||||
- MSC
|
||||
- Invoke only scsi complete callback after status transaction is complete.
|
||||
- Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error.
|
||||
|
||||
- USBTMC
|
||||
- Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu
|
||||
- Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu
|
||||
|
||||
**Example**
|
||||
|
||||
- Support make from windows cmd.exe
|
||||
- Support make from windows cmd.exe
|
||||
- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples
|
||||
|
||||
### USB Host
|
||||
|
||||
USB Host
|
||||
--------
|
||||
|
||||
No noticeable changes to host stack
|
||||
|
||||
### New Boards
|
||||
New Boards
|
||||
----------
|
||||
|
||||
- NXP/Freescale Freedom FRDM-KL25Z
|
||||
- Feather Double M33 express
|
||||
@ -241,14 +387,18 @@ No noticeable changes to host stack
|
||||
- Adafruit PyPortal
|
||||
- Great Scott Gadgets' LUNA D11 & D21
|
||||
|
||||
## 0.7.0 - 2020.11.08
|
||||
|
||||
### Device Controller Driver
|
||||
0.7.0 (2020-11-08)
|
||||
==================
|
||||
|
||||
Device Controller Driver
|
||||
------------------------
|
||||
|
||||
- Added new support for Espressif ESP32-S2
|
||||
- Added new support for Dialog DA1469x
|
||||
- Enhance STM32 Synopsys
|
||||
- Support bus events disconnection/suspend/resume/wakeup
|
||||
|
||||
- Support bus events disconnection/suspend/resume/wakeup
|
||||
- Improve transfer performance with optimizing xfer and fifo size
|
||||
- Support Highspeed port (OTG_HS) with both internal and external PHY
|
||||
- Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY)
|
||||
@ -256,23 +406,30 @@ No noticeable changes to host stack
|
||||
- Fix FIFO flush during stall
|
||||
- Implement dcd_edpt_close() API
|
||||
- Support F105, F107
|
||||
|
||||
- Enhance STM32 fsdev
|
||||
- Improve dcd fifo allocation
|
||||
- Fix ISTR race condition
|
||||
- Support remap USB IRQ on supported MCUs
|
||||
- Implement dcd_edpt_close() API
|
||||
|
||||
- Enhance NUC 505: enhance set configure behavior
|
||||
|
||||
- Enhance SAMD
|
||||
- Fix race condition with setup packet
|
||||
- Add SAMD11 option `OPT_MCU_SAMD11`
|
||||
- Add SAME5x option `OPT_MCU_SAME5X`
|
||||
|
||||
- Fix SAMG control data toggle and stall race condition
|
||||
|
||||
- Enhance nRF
|
||||
- Fix hanged when tud_task() is called within critical section (disabled interrupt)
|
||||
- Fix disconnect bus event not submitted
|
||||
- Implement ISO transfer and dcd_edpt_close()
|
||||
|
||||
### USB Device
|
||||
|
||||
USB Device
|
||||
----------
|
||||
|
||||
**USBD**
|
||||
|
||||
@ -289,10 +446,12 @@ No noticeable changes to host stack
|
||||
- Add IAR compiler support
|
||||
- Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument
|
||||
- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()`
|
||||
|
||||
- Enhance class driver management
|
||||
- `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver
|
||||
- Add application implemented class driver via `usbd_app_driver_get_cb()`
|
||||
- IAD is handled to assign driver id
|
||||
|
||||
- Added `tud_descriptor_device_qualifier_cb()` callback
|
||||
- Optimize `tu_fifo` bulk write/read transfer
|
||||
- Forward non-std control request to class driver
|
||||
@ -303,43 +462,54 @@ No noticeable changes to host stack
|
||||
|
||||
- USBNET: remove ACM-EEM due to lack of support from host
|
||||
- USBTMC: fix descriptors when INT EP is disabled
|
||||
|
||||
- CDC:
|
||||
- Send zero length packet for end of data when needed
|
||||
- Add `tud_cdc_tx_complete_cb()` callback
|
||||
- Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo
|
||||
|
||||
- MIDI:
|
||||
- Add packet interface
|
||||
- Add multiple jack descriptors
|
||||
- Fix MIDI driver for sysex
|
||||
|
||||
- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request
|
||||
|
||||
- Rename some configure macro to make it clear that those are used directly for endpoint transfer
|
||||
- CFG_TUD_HID_BUFSIZE to `CFG_TUD_HID_EP_BUFSIZE
|
||||
- CFG_TUD_HID_BUFSIZE to CFG_TUD_HID_EP_BUFSIZE
|
||||
- CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE
|
||||
- CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE
|
||||
- CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE
|
||||
|
||||
- HID:
|
||||
- Fix gamepad template descriptor
|
||||
- Add multiple HID interface API
|
||||
- Add extra comma to HID_REPORT_ID
|
||||
|
||||
### USB Host
|
||||
USB Host
|
||||
--------
|
||||
|
||||
- Rework USB host stack (still work in progress)
|
||||
- Fix compile error with pipehandle
|
||||
- Rework usbh control and enumeration as non-blocking
|
||||
- Fix compile error with pipehandle
|
||||
- Rework usbh control and enumeration as non-blocking
|
||||
|
||||
- Improve Hub, MSC, HID host driver
|
||||
|
||||
### Examples
|
||||
Examples
|
||||
--------
|
||||
|
||||
- Add new hid_composite_freertos
|
||||
- Add new dynamic_configuration to demonstrate how to switch configuration descriptors
|
||||
- Add new hid_multiple_interface
|
||||
|
||||
- Enhance `net_lwip_webserver` example
|
||||
- Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both)
|
||||
- Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver
|
||||
|
||||
- Added new Audio example: audio_test uac2_headsest
|
||||
|
||||
### New Boards
|
||||
New Boards
|
||||
----------
|
||||
|
||||
- Espressif ESP32-S2: saola_1, kaluga_1
|
||||
- STM32: F746 Nucleo, H743 Eval, H743 Nucleo, F723 discovery, stlink v3 mini, STM32L4r5 Nucleo
|
||||
@ -347,13 +517,16 @@ No noticeable changes to host stack
|
||||
- Microchip: Great Scoot Gadgets' LUNA, samd11_xplained, D5035-01, atsamd21 xplained pro
|
||||
- nRF: ItsyBitsy nRF52840
|
||||
|
||||
## 0.6.0 - 2020.03.30
|
||||
|
||||
Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release.
|
||||
0.6.0 (2020-03-30)
|
||||
==================
|
||||
|
||||
### Added
|
||||
Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to `Nathan Conrad <https://github.com/pigrew>`__ , `Peter Lawrence <https://github.com/majbthrd>`__ , `William D. Jones <https://github.com/cr1901>`__ and `Sean Cross <https://github.com/xobs>`__ and others for spending their precious time to add lots of features and ports for this release.
|
||||
|
||||
**MCUs**
|
||||
Added
|
||||
-----
|
||||
|
||||
**MCU**
|
||||
|
||||
- Added support for Microchip SAMG55
|
||||
- Added support for Nordic nRF52833
|
||||
@ -389,68 +562,14 @@ Following examples are added:
|
||||
- usbtmc
|
||||
- webusb_serial
|
||||
|
||||
**Boards**
|
||||
|
||||
Following boards are added:
|
||||
|
||||
- adafruit_clue
|
||||
- arduino_nano33_ble
|
||||
- circuitplayground_bluefruit
|
||||
- circuitplayground_express
|
||||
- feather_m0_express
|
||||
- feather_nrf52840_sense
|
||||
- feather_stm32f405
|
||||
- fomu
|
||||
- itsybitsy_m0
|
||||
- itsybitsy_m4
|
||||
- lpcxpresso11u37
|
||||
- lpcxpresso1549
|
||||
- lpcxpresso51u68
|
||||
- lpcxpresso54114
|
||||
- lpcxpresso55s69
|
||||
- mbed1768
|
||||
- mimxrt1010_evk
|
||||
- mimxrt1015_evk
|
||||
- mimxrt1020_evk
|
||||
- mimxrt1050_evkb
|
||||
- mimxrt1060_evk
|
||||
- mimxrt1064_evk
|
||||
- msp_exp430f5529lp
|
||||
- ngx4330
|
||||
- nrf52840_mdk_dongle
|
||||
- nutiny_nuc121s
|
||||
- nutiny_nuc125s
|
||||
- nutiny_nuc126v
|
||||
- nutiny_sdk_nuc120
|
||||
- nutiny_sdk_nuc505
|
||||
- pca10059
|
||||
- pca10100
|
||||
- pyboardv11
|
||||
- raytac_mdbt50q_rx
|
||||
- samg55xplained
|
||||
- seeeduino_xiao
|
||||
- spresense
|
||||
- stm32f070rbnucleo
|
||||
- stm32f072disco
|
||||
- stm32f103bluepill
|
||||
- stm32f207nucleo
|
||||
- stm32f401blackpill
|
||||
- stm32f411blackpill
|
||||
- stm32f411disco
|
||||
- stm32f412disco
|
||||
- stm32f767nucleo
|
||||
- stm32h743nucleo
|
||||
- stm32l0538disco
|
||||
- stm32l476disco
|
||||
- teensy_40
|
||||
|
||||
### Changed
|
||||
Changed
|
||||
-------
|
||||
|
||||
- Changed `tud_descriptor_string_cb()` to have additional Language ID argument
|
||||
- Merged hal_nrf5x.c into dcd_nrf5x.c
|
||||
- Merged dcd_samd21.c and dcd_samd51.c into dcd_samd.c
|
||||
- Generalized dcd_stm32f4.c to dcd_synopsys.c
|
||||
- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs
|
||||
- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs
|
||||
- Improved DCD SAMD stability, fix missing setup packet occasionally
|
||||
- Improved usbd/usbd_control with proper hanlding of zero-length packet (ZLP)
|
||||
- Improved STM32 DCD FSDev
|
||||
@ -460,9 +579,12 @@ Following boards are added:
|
||||
- Fixed mynewt osal queue definition
|
||||
- Fixed cdc_msc_freertos example build for all MCUs
|
||||
|
||||
## 0.5.0 (Initial Release) - 2019.07.10
|
||||
|
||||
First release, device stack works great, host stack works but still need improvement.
|
||||
- Special thanks to @adafruit team, especially @tannewt to help out immensely to rework device stack: simplify osal & control transfer, adding SAMD21/SAMD51 ports, writing porting docs, adding MIDI class support etc...
|
||||
0.5.0 (2019-06)
|
||||
===============
|
||||
|
||||
First release, device stack works great, host stack works but still need improvement.
|
||||
|
||||
- Special thanks to @adafruit team, especially @tannewt to help out immensely to rework device stack: simplify osal & control transfer, adding SAMD21/SAMD51 ports, writing porting docs, adding MIDI class support etc...
|
||||
- Thanks to @cr1901 for adding STM32F4 port.
|
||||
- Thanks to @PTS93 and @todbot for HID raw API
|
1
docs/info/contributors.rst
Symbolic link
1
docs/info/contributors.rst
Symbolic link
@ -0,0 +1 @@
|
||||
../../CONTRIBUTORS.rst
|
13
docs/info/index.rst
Normal file
13
docs/info/index.rst
Normal file
@ -0,0 +1,13 @@
|
||||
****
|
||||
Info
|
||||
****
|
||||
|
||||
Index
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
uses
|
||||
changelog
|
||||
contributors
|
17
docs/info/uses.rst
Normal file
17
docs/info/uses.rst
Normal file
@ -0,0 +1,17 @@
|
||||
****
|
||||
Uses
|
||||
****
|
||||
|
||||
TinyUSB is currently used by these other projects:
|
||||
|
||||
- `Adafruit nRF52 Arduino <https://github.com/adafruit/Adafruit_nRF52_Arduino>`__
|
||||
- `Adafruit nRF52 Bootloader <https://github.com/adafruit/Adafruit_nRF52_Bootloader>`__
|
||||
- `Adafruit SAMD Arduino <https://github.com/adafruit/ArduinoCore-samd>`__
|
||||
- `CircuitPython <https://github.com/adafruit/circuitpython>`__
|
||||
- `Espressif IDF <https://github.com/espressif/esp-idf>`__
|
||||
- `MicroPython <https://github.com/micropython/micropython>`__
|
||||
- `mynewt <https://mynewt.apache.org>`__
|
||||
- `openinput <https://github.com/openinput-fw/openinput>`__
|
||||
- `Raspberry Pi Pico SDK <https://github.com/raspberrypi/pico-sdk>`__
|
||||
- `TinyUF2 Bootloader <https://github.com/adafruit/tinyuf2>`__
|
||||
- `TinyUSB Arduino Library <https://github.com/adafruit/Adafruit_TinyUSB_Arduino>`__
|
@ -1,36 +1,42 @@
|
||||
# Concurrency
|
||||
***********
|
||||
Concurrency
|
||||
***********
|
||||
|
||||
The TinyUSB library is designed to operate on single-core MCUs with multi-threaded applications in mind. Interaction with interrupts is especially important to pay attention to.
|
||||
It is compatible with optionally using a RTOS.
|
||||
|
||||
## General
|
||||
General
|
||||
-------
|
||||
|
||||
When writing code, keep in mind that the OS (if using a RTOS) may swap out your code at any time. Also, your code can be preempted by an interrupt at any time.
|
||||
|
||||
## Application Code
|
||||
Application Code
|
||||
----------------
|
||||
|
||||
The USB core does not execute application callbacks while in an interrupt context. Calls to application code are from within the USB core task context. Note that the application core will call class drivers from within their own task.
|
||||
|
||||
## Class Drivers
|
||||
Class Drivers
|
||||
-------------
|
||||
|
||||
Class driver code should never be called from an interrupt context by the USB core, though the application is allowed to call class driver functions from interrupts. USB core functions may be called simultaneously by multiple tasks. Use care that proper locking is used to guard the USBD core functions from this case.
|
||||
|
||||
Class drivers are allowed to call `usbd_*` functions, but not `dcd_*` functions.
|
||||
Class drivers are allowed to call ``usbd_*`` functions, but not ``dcd_*`` functions.
|
||||
|
||||
## USB Core
|
||||
USB Core
|
||||
--------
|
||||
|
||||
All functions that may be called from an (USB core) interrupt context have a `bool in_isr` parameter to remind the implementer that special care must be taken.
|
||||
All functions that may be called from an (USB core) interrupt context have a ``bool in_isr`` parameter to remind the implementer that special care must be taken.
|
||||
|
||||
Interrupt handlers must not directly call class driver code, they must pass a message to the USB core's task.
|
||||
|
||||
`usbd_*` functions may be called from interrupts without any notice. They may also be called simultaneously by multiple tasks.
|
||||
``usbd_*`` functions may be called from interrupts without any notice. They may also be called simultaneously by multiple tasks.
|
||||
|
||||
## Device Drivers
|
||||
Device Drivers
|
||||
--------------
|
||||
|
||||
Much of the processing of the USB stack is done in an interrupt context, and care must be taken in order to ensure variables are handled in the appropriate ways by the compiler and optimizer.
|
||||
|
||||
In particular:
|
||||
|
||||
- Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory access (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like `_I`, `_O`, or `_IO'.
|
||||
- All defined global variables are marked as `static`.
|
||||
|
||||
* Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory access (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like _I , _O , or _IO.
|
||||
* All defined global variables are marked as ``static``.
|
189
docs/reference/getting_started.rst
Normal file
189
docs/reference/getting_started.rst
Normal file
@ -0,0 +1,189 @@
|
||||
***************
|
||||
Getting Started
|
||||
***************
|
||||
|
||||
Add TinyUSB to your project
|
||||
---------------------------
|
||||
|
||||
It is relatively simple to incorporate tinyusb to your (existing) project
|
||||
|
||||
|
||||
* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb*
|
||||
* Add all the .c in the ``tinyusb/src`` folder to your project
|
||||
* Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h.
|
||||
* Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards).
|
||||
* If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work.
|
||||
* Add tusb_init() call to your reset initialization code.
|
||||
* Call ``tud_int_handler()`` (device) and/or ``tuh_int_handler()`` (host) in your USB IRQ Handler
|
||||
* Implement all enabled classes's callbacks.
|
||||
* If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner.
|
||||
|
||||
.. code-block::
|
||||
|
||||
int main(void)
|
||||
{
|
||||
your_init_code();
|
||||
tusb_init(); // initialize tinyusb stack
|
||||
|
||||
while(1) // the mainloop
|
||||
{
|
||||
your_application_code();
|
||||
|
||||
tud_task(); // device task
|
||||
tuh_task(); // host task
|
||||
}
|
||||
}
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of `the supported Boards <boards.md>`_. Firstly we need to ``git clone`` if not already
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ git clone https://github.com/hathach/tinyusb tinyusb
|
||||
$ cd tinyusb
|
||||
|
||||
Some TinyUSB examples also requires external submodule libraries in ``/lib`` such as FreeRTOS, Lightweight IP to build. Run following command to fetch them
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ git submodule update --init lib
|
||||
|
||||
In addition, MCU driver submodule is also needed to provide low-level MCU peripheral's driver. Luckily, it will be fetched if needed when you run the ``make`` to build your board.
|
||||
|
||||
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
|
||||
|
||||
Build
|
||||
^^^^^
|
||||
|
||||
To build example, first change directory to an example folder.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ cd examples/device/cdc_msc
|
||||
|
||||
Then compile with ``make BOARD=[board_name] all``\ , for example
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express all
|
||||
|
||||
Note: ``BOARD`` can be found as directory name in ``hw/bsp``\ , either in its family/boards or directly under bsp (no family).
|
||||
|
||||
Port Selection
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=stm32f746disco PORT=1 all
|
||||
|
||||
Port Speed
|
||||
~~~~~~~~~~
|
||||
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=stm32f746disco SPEED=full all
|
||||
|
||||
Debug
|
||||
^^^^^
|
||||
|
||||
To compile for debugging add ``DEBUG=1``\ , for example
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express DEBUG=1 all
|
||||
|
||||
Log
|
||||
~~~
|
||||
|
||||
Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 all
|
||||
|
||||
Logger
|
||||
~~~~~~
|
||||
|
||||
By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols:
|
||||
|
||||
|
||||
* `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/)
|
||||
|
||||
* Cons: requires jlink as the debugger.
|
||||
* Pros: work with most if not all MCUs
|
||||
* Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package.
|
||||
|
||||
* ``LOGGER=swo``\ : Use dedicated SWO pin of ARM Cortex SWD debug header.
|
||||
|
||||
* Cons: only work with ARM Cortex MCUs minus M0
|
||||
* Pros: should be compatible with more debugger that support SWO.
|
||||
* Software viewer should be provided along with your debugger driver.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
|
||||
|
||||
Flash
|
||||
^^^^^
|
||||
|
||||
``flash`` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express flash
|
||||
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
|
||||
|
||||
Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express flash-jlink
|
||||
|
||||
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make BOARD=feather_nrf52840_express all uf2
|
||||
|
||||
IAR Support
|
||||
-----------
|
||||
|
||||
IAR Project Connection files are provided to import TinyUSB stack into your project.
|
||||
|
||||
* A buldable project of your MCU need to be created in advance.
|
||||
|
||||
|
||||
* Take example of STM32F0:
|
||||
|
||||
- You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`.
|
||||
|
||||
- `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs.
|
||||
|
||||
* Open `Tools -> Configure Custom Argument Variables` (Switch to `Global` tab if you want to do it for all your projects)
|
||||
Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack,
|
||||
for example `C:\\tinyusb`
|
||||
|
||||
Import stack only
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`.
|
||||
|
||||
Run examples
|
||||
^^^^^^^^^^^^
|
||||
|
||||
1. (Python3 is needed) Run `iar_gen.py` to generate .ipcf files of examples:
|
||||
|
||||
.. code-block::
|
||||
|
||||
cd C:\tinyusb\tools
|
||||
python iar_gen.py
|
||||
|
||||
2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`.
|
||||
For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`
|
59
docs/reference/index.rst
Normal file
59
docs/reference/index.rst
Normal file
@ -0,0 +1,59 @@
|
||||
*********
|
||||
Reference
|
||||
*********
|
||||
|
||||
.. figure:: ../assets/stack.svg
|
||||
:width: 1600px
|
||||
:alt: stackup
|
||||
|
||||
representation of the TinyUSB stack.
|
||||
|
||||
Device Stack
|
||||
============
|
||||
|
||||
Supports multiple device configurations by dynamically changing usb descriptors. Low power functions such like suspend, resume, and remote wakeup. Following device classes are supported:
|
||||
|
||||
- Audio Class 2.0 (UAC2)
|
||||
- Bluetooth Host Controller Interface (BTH HCI)
|
||||
- Communication Class (CDC)
|
||||
- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme
|
||||
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
|
||||
- Mass Storage Class (MSC): with multiple LUNs
|
||||
- Musical Instrument Digital Interface (MIDI)
|
||||
- Network with RNDIS, CDC-ECM (work in progress)
|
||||
- USB Test and Measurement Class (USBTMC)
|
||||
- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
|
||||
- `WebUSB <https://github.com/WICG/webusb>`__ with vendor-specific class
|
||||
|
||||
If you have special need, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how RPi team add their reset interface [raspberrypi/pico-sdk#197](https://github.com/raspberrypi/pico-sdk/pull/197)
|
||||
|
||||
Host Stack
|
||||
==========
|
||||
|
||||
- Human Interface Device (HID): Keyboard, Mouse, Generic
|
||||
- Mass Storage Class (MSC)
|
||||
- Hub currently only supports 1 level of hub (due to my laziness)
|
||||
|
||||
OS Abstraction layer
|
||||
====================
|
||||
|
||||
TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box.
|
||||
|
||||
- **No OS**
|
||||
- **FreeRTOS**
|
||||
- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example)
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
All TinyUSB sources in the `src` folder are licensed under MIT license. However, each file can be individually licensed especially those in `lib` and `hw/mcu` folder. Please make sure you understand all the license term for files you use in your project.
|
||||
|
||||
Index
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
supported
|
||||
getting_started
|
||||
concurrency
|
338
docs/reference/supported.rst
Normal file
338
docs/reference/supported.rst
Normal file
@ -0,0 +1,338 @@
|
||||
*****************
|
||||
Supported Devices
|
||||
*****************
|
||||
|
||||
|
||||
Supported MCUs
|
||||
==============
|
||||
|
||||
.. admonition:: Warning
|
||||
:class: warning
|
||||
|
||||
This table is a WIP! the data is not correct, tho if a device is listed, it likely works as a usb full speed device at the least.
|
||||
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Manufacturer | Family | Device | Host | FS | HS | Known Issues |
|
||||
+==============+====================+===================+====================+===================+===================+==============+
|
||||
| Dialog | DA1469x | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Espressif | ESP32-S2 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | ESP32-S3 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| MicroChip | SAMD11 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAMD21 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAMD51 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAME5x | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAMG55 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAML21 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAML22 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | SAME70,S70,V70,V71 | |:green_square:| | |:red_square:| | |:green_square:| | |:green_square:| | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| NordicSemi | nRF52833 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | nRF52840 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Nuvoton | NUC120 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | NUC121/NUC125 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | NUC126 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | NUC505 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| NXP | iMX | RT1011 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | RT1015 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | RT1021 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | RT1052 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | RT1062 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | RT1064 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | Kinetis KL25 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | LPC | 11u | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 13 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 15 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 17 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 18 | | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 40 | | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 43 | |:green_square:| | |:yellow_square:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 51u | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 54 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | 55 | |:green_square:| | |:x:| | |:green_square:| | | |
|
||||
+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Raspberry Pi | RP2040 | |:green_square:| | |:x:| | |:green_square:| | | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Renesas | RX63N | |:green_square:| | | |:green_square:| | |:x:| | |
|
||||
| +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | RX65N | |:green_square:| | | |:green_square:| | |:x:| | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Silabs | EFM32GG12 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | #750 |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| Sony | CXD56 | |:green_square:| | |:x:| | |:green_square:| | |:x:| | |
|
||||
+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| ST | STM32 | L0 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F0 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F1 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F2 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F3 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F4 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | F7 | |:green_square:| | | |:green_square:| | | |
|
||||
| | +------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| | | H7 | |:green_square:| | | |:green_square:| | |:green_square:| | |
|
||||
+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| TI | MSP430 | |:green_square:| | | |:green_square:| | | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
| ValentyUSB | eptri | |:green_square:| | | |:green_square:| | | |
|
||||
+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
|
||||
|
||||
Table Legend
|
||||
------------
|
||||
|
||||
================= ===================
|
||||
|:x:| Not available
|
||||
|:red_square:| Not supported
|
||||
|:yellow_square:| WIP/partial support
|
||||
|:green_square:| Supported
|
||||
================= ===================
|
||||
|
||||
Supported Boards
|
||||
================
|
||||
|
||||
The board support code is only used for self-contained examples and testing. It is not used when TinyUSB is part of a larger project. It is responsible for getting the MCU started and the USB peripheral clocked with minimal of on-board devices
|
||||
|
||||
- One LED : for status
|
||||
- One Button : to get input from user
|
||||
- One UART : optional for device, but required for host examples
|
||||
|
||||
The following boards are supported (sorted alphabetically):
|
||||
|
||||
Dialog DA146xx
|
||||
--------------
|
||||
|
||||
- `DA14695 Development Kit – USB <https://www.dialog-semiconductor.com/products/da14695-development-kit-usb>`__
|
||||
- `DA1469x Development Kit – Pro <https://www.dialog-semiconductor.com/products/da14695-development-kit-pro>`__
|
||||
|
||||
Espressif ESP32-S2
|
||||
------------------
|
||||
|
||||
- Adafruit Feather ESP32-S2
|
||||
- `Adafruit Magtag 2.9" E-Ink WiFi Display <https://www.adafruit.com/product/4800>`__
|
||||
- `Adafruit Metro ESP32-S2 <https://www.adafruit.com/product/4775>`__
|
||||
- `ESP32-S2-Kaluga-1 <https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html>`__
|
||||
- `ESP32-S2-Saola-1 <https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html>`__
|
||||
|
||||
MicroChip
|
||||
---------
|
||||
|
||||
SAMD11 & SAMD21
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- `Adafruit Circuit Playground Express <https://www.adafruit.com/product/3333>`__
|
||||
- `Adafruit Feather M0 Express <https://www.adafruit.com/product/3403>`__
|
||||
- `Adafruit ItsyBitsy M0 Express <https://www.adafruit.com/product/3727>`__
|
||||
- `Adafruit Metro M0 Express <https://www.adafruit.com/product/3505>`__
|
||||
- `Great Scott Gadgets LUNA <https://greatscottgadgets.com/luna/>`__
|
||||
- `Microchip SAMD11 Xplained Pro <https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro>`__
|
||||
- `Microchip SAMD21 Xplained Pro <https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMD21-XPRO>`__
|
||||
- `Seeeduino Xiao <https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html>`__
|
||||
|
||||
SAMD51 & SAME54
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- `Adafruit Feather M4 Express <https://www.adafruit.com/product/3857>`__
|
||||
- `Adafruit ItsyBitsy M4 Express <https://www.adafruit.com/product/3800>`__
|
||||
- `Adafruit PyBadge <https://www.adafruit.com/product/4200>`__
|
||||
- `Adafruit PyPortal <https://www.adafruit.com/product/4116>`__
|
||||
- `Adafruit Metro M4 Express <https://www.adafruit.com/product/3382>`__
|
||||
- `D5035-01 <https://github.com/RudolphRiedel/USB_CAN-FD>`__
|
||||
- `Microchip SAME54 Xplained Pro <https://www.microchip.com/developmenttools/productdetails/atsame54-xpro>`__
|
||||
|
||||
SAMG
|
||||
^^^^
|
||||
|
||||
- `Microchip SAMG55 Xplained Pro <https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO>`__
|
||||
|
||||
SAML2x
|
||||
^^^^^^
|
||||
|
||||
- `SAML21 Xplaind Pro <https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAML21-XPRO-B>`__
|
||||
- `SAML22 Feather <https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather>`__
|
||||
- `Sensor Watch <https://github.com/joeycastillo/Sensor-Watch>`__
|
||||
|
||||
Nordic nRF5x
|
||||
------------
|
||||
|
||||
- `Adafruit Circuit Playground Bluefruit <https://www.adafruit.com/product/4333>`__
|
||||
- `Adafruit CLUE <https://www.adafruit.com/product/4500>`__
|
||||
- `Adafruit Feather nRF52840 Express <https://www.adafruit.com/product/4062>`__
|
||||
- `Adafruit Feather nRF52840 Sense <https://www.adafruit.com/product/4516>`__
|
||||
- `Adafruit ItsyBitsy nRF52840 Express <https://www.adafruit.com/product/4481>`__
|
||||
- `Arduino Nano 33 BLE <https://store.arduino.cc/usa/nano-33-ble>`__
|
||||
- `Arduino Nano 33 BLE Sense <https://store.arduino.cc/usa/nano-33-ble-sense>`__
|
||||
- `Maker Diary nRF52840 MDK Dongle <https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle>`__
|
||||
- `Nordic nRF52840 Development Kit (aka pca10056) <https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK>`__
|
||||
- `Nordic nRF52840 Dongle (aka pca10059) <https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle>`__
|
||||
- `Nordic nRF52833 Development Kit (aka pca10100) <https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK>`__
|
||||
- `Raytac MDBT50Q-RX Dongle <https://www.raytac.com/product/ins.php?index_id=89>`__
|
||||
|
||||
Nuvoton
|
||||
-------
|
||||
|
||||
- NuTiny SDK NUC120
|
||||
- `NuTiny NUC121S <https://direct.nuvoton.com/en/nutiny-nuc121s>`__
|
||||
- `NuTiny NUC125S <https://direct.nuvoton.com/en/nutiny-nuc125s>`__
|
||||
- `NuTiny NUC126V <https://direct.nuvoton.com/en/nutiny-nuc126v>`__
|
||||
- `NuTiny SDK NUC505Y <https://direct.nuvoton.com/en/nutiny-nuc505y>`__
|
||||
|
||||
NXP
|
||||
---
|
||||
|
||||
iMX RT
|
||||
^^^^^^
|
||||
|
||||
- `MIMX RT1010 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1010-evaluation-kit:MIMXRT1010-EVK>`__
|
||||
- `MIMX RT1015 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1015-evaluation-kit:MIMXRT1015-EVK>`__
|
||||
- `MIMX RT1020 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1020-evaluation-kit:MIMXRT1020-EVK>`__
|
||||
- `MIMX RT1050 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1050-evaluation-kit:MIMXRT1050-EVK>`__
|
||||
- `MIMX RT1060 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1060-evk-i.mx-rt1060-evaluation-kit:MIMXRT1060-EVK>`__
|
||||
- `MIMX RT1064 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1064-evk-i.mx-rt1064-evaluation-kit:MIMXRT1064-EVK>`__
|
||||
- `Teensy 4.0 Development Board <https://www.pjrc.com/store/teensy40.html>`__
|
||||
|
||||
Kinetis
|
||||
^^^^^^^
|
||||
|
||||
- `FRDM-KL25Z <https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z>`__
|
||||
|
||||
LPC 11-13-15
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- `LPCXpresso 11u37 <https://www.nxp.com/design/microcontrollers-developer-resources/lpcxpresso-boards/lpcxpresso-board-for-lpc11u37h:OM13074>`__
|
||||
- `LPCXpresso 11u68 <https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc11u68:OM13058>`__
|
||||
- `LPCXpresso 1347 <https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc1347:OM13045>`__
|
||||
- `LPCXpresso 1549 <https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1500-cortex-m3/lpcxpresso-board-for-lpc1549:OM13056>`__
|
||||
|
||||
LPC 17-40
|
||||
^^^^^^^^^
|
||||
|
||||
- `ARM mbed LPC1768 <https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc1700-cortex-m3/arm-mbed-lpc1768-board:OM11043>`__
|
||||
- `Embedded Artists LPC4088 Quick Start board <https://www.embeddedartists.com/products/lpc4088-quickstart-board>`__
|
||||
- `LPCXpresso 1769 <https://www.nxp.com/support/developer-resources/evaluation-and-development-boards/lpcxpresso-boards/lpcxpresso-board-for-lpc1769:OM13000>`__
|
||||
|
||||
LPC 18-43
|
||||
^^^^^^^^^
|
||||
|
||||
- `Embedded Artists LPC4357 Developer Kit <http://www.embeddedartists.com/products/kits/lpc4357_kit.php>`__
|
||||
- `Keil MCB1800 Evaluation Board <http://www.keil.com/mcb1800>`__
|
||||
- `LPCXpresso18S37 Development Board <https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc4000-cortex-m4/lpcxpresso18s37-development-board:OM13076>`__
|
||||
- `NGX LPC4330-Xplorer <https://www.nxp.com/design/designs/lpc4330-xplorer-board:OM13027>`__
|
||||
|
||||
LPC 51
|
||||
^^^^^^
|
||||
|
||||
- `LPCXpresso 51U68 <https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpcxpresso51u68-for-the-lpc51u68-mcus:OM40005>`__
|
||||
|
||||
LPC 54
|
||||
^^^^^^
|
||||
|
||||
- `LPCXpresso 54114 <https://www.nxp.com/design/microcontrollers-developer-resources/lpcxpresso-boards/lpcxpresso54114-board:OM13089>`__
|
||||
|
||||
LPC55
|
||||
^^^^^
|
||||
|
||||
- `Double M33 Express <https://www.crowdsupply.com/steiert-solutions/double-m33-express>`__
|
||||
- `LPCXpresso 55s28 EVK <https://www.nxp.com/design/software/development-software/lpcxpresso55s28-development-board:LPC55S28-EVK>`__
|
||||
- `LPCXpresso 55s69 EVK <https://www.nxp.com/design/development-boards/lpcxpresso-boards/lpcxpresso55s69-development-board:LPC55S69-EVK>`__
|
||||
- `MCU-Link <https://www.nxp.com/design/development-boards/lpcxpresso-boards/mcu-link-debug-probe:MCU-LINK>`__
|
||||
|
||||
Renesas RX
|
||||
----------
|
||||
|
||||
- `GR-CITRUS <https://www.renesas.com/us/en/products/gadget-renesas/boards/gr-citrus>`__
|
||||
- `Renesas RX65N Target Board <https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rtk5rx65n0c00000br-target-board-rx65n>`__
|
||||
|
||||
Raspberry Pi RP2040
|
||||
-------------------
|
||||
|
||||
- `Adafruit Feather RP2040 <https://www.adafruit.com/product/4884>`__
|
||||
- `Adafruit ItsyBitsy RP2040 <https://www.adafruit.com/product/4888>`__
|
||||
- `Adafruit QT Py RP2040 <https://www.adafruit.com/product/4900>`__
|
||||
- `Raspberry Pi Pico <https://www.raspberrypi.org/products/raspberry-pi-pico/>`__
|
||||
|
||||
Silabs
|
||||
------
|
||||
|
||||
- `EFM32GG12 Thunderboard Kit (SLTB009A) <https://www.silabs.com/development-tools/thunderboard/thunderboard-gg12-kit>`__
|
||||
|
||||
Sony
|
||||
----
|
||||
|
||||
- `Sony Spresense CXD5602 <https://developer.sony.com/develop/spresense>`__
|
||||
|
||||
ST STM32
|
||||
--------
|
||||
|
||||
- `Adafruit Feather STM32F405 <https://www.adafruit.com/product/4382>`__
|
||||
- `Micro Python PyBoard v1.1 <https://store.micropython.org/product/PYBv1.1>`__
|
||||
- `STLink-V3 Mini <https://www.st.com/en/development-tools/stlink-v3mini.html>`__
|
||||
- `STM32 L035c8 Discovery <https://www.st.com/en/evaluation-tools/32l0538discovery.html>`__
|
||||
- `STM32 L4R5zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html>`__
|
||||
- `STM32 F070rb Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f070rb.html>`__
|
||||
- `STM32 F072 Evaluation <https://www.st.com/en/evaluation-tools/stm32072b-eval.html>`__
|
||||
- `STM32 F072rb Discovery <https://www.st.com/en/evaluation-tools/32f072bdiscovery.html>`__
|
||||
- `STM32 F103c8 Blue Pill <https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill>`__
|
||||
- `STM32 F103rc Mini v2.0 <https://stm32-base.org/boards/STM32F103RCT6-STM32-Mini-V2.0>`__
|
||||
- `STM32 F207zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f207zg.html>`__
|
||||
- `STM32 F303vc Discovery <https://www.st.com/en/evaluation-tools/stm32f3discovery.html>`__
|
||||
- `STM32 F401cc Black Pill <https://stm32-base.org/boards/STM32F401CCU6-WeAct-Black-Pill-V1.2>`__
|
||||
- `STM32 F407vg Discovery <https://www.st.com/en/evaluation-tools/stm32f4discovery.html>`__
|
||||
- `STM32 F411ce Black Pill <https://www.adafruit.com/product/4877>`__
|
||||
- `STM32 F411ve Discovery <https://www.st.com/en/evaluation-tools/32f411ediscovery.html>`__
|
||||
- `STM32 F412zg Discovery <https://www.st.com/en/evaluation-tools/32f412gdiscovery.html>`__
|
||||
- `STM32 F412zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f412zg.html>`__
|
||||
- `STM32 F723e Discovery <https://www.st.com/en/evaluation-tools/32f723ediscovery.html>`__
|
||||
- `STM32 F746zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f746zg.html>`__
|
||||
- `STM32 F746g Discovery <https://www.st.com/en/evaluation-tools/32f746gdiscovery.html>`__
|
||||
- `STM32 F767zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f767zi.html>`__
|
||||
- `STM32 F769i Discovery <https://www.st.com/en/evaluation-tools/32f769idiscovery.html>`__
|
||||
- `STM32 H743zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-h743zi.html>`__
|
||||
- `STM32 H743i Evaluation <https://www.st.com/en/evaluation-tools/stm32h743i-eval.html>`__
|
||||
- `STM32 H745i Discovery <https://www.st.com/en/evaluation-tools/stm32h745i-disco.html>`__
|
||||
- `Waveshare OpenH743I-C <https://www.waveshare.com/openh743i-c-standard.htm>`__
|
||||
|
||||
TI
|
||||
--
|
||||
|
||||
- `MSP430F5529 USB LaunchPad Evaluation Kit <http://www.ti.com/tool/MSP-EXP430F5529LP>`__
|
||||
|
||||
Tomu
|
||||
----
|
||||
|
||||
- `Fomu <https://www.crowdsupply.com/sutajio-kosagi/fomu>`__
|
4
docs/requirements.txt
Normal file
4
docs/requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
sphinx~=3.0
|
||||
furo>=2020.12.30.b24
|
||||
sphinxemoji>=0.1.8
|
||||
sphinx-autodoc-typehints>=1.10
|
@ -92,7 +92,7 @@ enum
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN)
|
||||
|
@ -92,7 +92,7 @@ enum
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN)
|
||||
|
@ -48,7 +48,7 @@
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
|
@ -35,6 +35,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
@ -51,7 +54,7 @@ tusb_desc_device_t const desc_device =
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -87,43 +90,98 @@ enum
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_DATA 0x02
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x82
|
||||
|
||||
#define EPNUM_CDC_1_NOTIF 0x84
|
||||
#define EPNUM_CDC_1_DATA 0x05
|
||||
#define EPNUM_CDC_1_OUT 0x05
|
||||
#define EPNUM_CDC_1_IN 0x85
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x83
|
||||
|
||||
#define EPNUM_CDC_1_NOTIF 0x84
|
||||
#define EPNUM_CDC_1_OUT 0x05
|
||||
#define EPNUM_CDC_1_IN 0x86
|
||||
|
||||
#else
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_DATA 0x02
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x82
|
||||
|
||||
#define EPNUM_CDC_1_NOTIF 0x83
|
||||
#define EPNUM_CDC_1_DATA 0x04
|
||||
#define EPNUM_CDC_1_OUT 0x04
|
||||
#define EPNUM_CDC_1_IN 0x84
|
||||
#endif
|
||||
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
|
||||
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
|
||||
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
|
@ -188,18 +188,35 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
bool tud_msc_is_writable_cb (uint8_t lun)
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Callback invoked when received WRITE10 command.
|
||||
// Process data in buffer to disk's storage and return number of written bytes
|
||||
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
@ -218,7 +235,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
|
||||
// read10 & write10 has their own callback and MUST not be handled here
|
||||
|
||||
void const* response = NULL;
|
||||
uint16_t resplen = 0;
|
||||
int32_t resplen = 0;
|
||||
|
||||
// most scsi handled is input
|
||||
bool in_xfer = true;
|
||||
|
@ -48,7 +48,7 @@
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
|
@ -35,32 +35,35 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
@ -82,8 +85,6 @@ enum
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
|
||||
@ -94,8 +95,8 @@ enum
|
||||
#define EPNUM_MSC_OUT 0x05
|
||||
#define EPNUM_MSC_IN 0x85
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG
|
||||
// SAMG doesn't support a same endpoint number with different direction IN and OUT
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
@ -126,10 +127,13 @@ enum
|
||||
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
// full speed configuration
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
@ -139,10 +143,13 @@ uint8_t const desc_fs_configuration[] =
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// high speed configuration
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
@ -150,7 +157,54 @@ uint8_t const desc_hs_configuration[] =
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
// Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
|
||||
memcpy(desc_other_speed_config,
|
||||
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
|
||||
CONFIG_TOTAL_LEN);
|
||||
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
|
0
examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X
Normal file
0
examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X
Normal file
@ -155,11 +155,14 @@ extern uint32_t SystemCoreClock;
|
||||
//--------------------------------------------------------------------+
|
||||
// Interrupt nesting behavior configuration.
|
||||
//--------------------------------------------------------------------+
|
||||
/* Cortex-M specific definitions. __NVIC_PRIO_BITS is defined in core_cmx.h */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
#if defined(__NVIC_PRIO_BITS)
|
||||
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#elif defined(__ECLIC_INTCTLBITS)
|
||||
// RISC-V Bumblebee core from nuclei
|
||||
#define configPRIO_BITS __ECLIC_INTCTLBITS
|
||||
#else
|
||||
#error "This port requires __NVIC_PRIO_BITS to be defined"
|
||||
#error "FreeRTOS configPRIO_BITS to be defined"
|
||||
#endif
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
|
||||
|
@ -94,7 +94,7 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RX63X
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
|
||||
#include "iodefine.h"
|
||||
void vApplicationSetupTimerInterrupt(void)
|
||||
{
|
||||
|
@ -178,6 +178,9 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
@ -190,6 +193,9 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
@ -208,7 +214,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
|
||||
// read10 & write10 has their own callback and MUST not be handled here
|
||||
|
||||
void const* response = NULL;
|
||||
uint16_t resplen = 0;
|
||||
int32_t resplen = 0;
|
||||
|
||||
// most scsi handled is input
|
||||
bool in_xfer = true;
|
||||
|
@ -35,6 +35,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -42,7 +45,7 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
@ -52,7 +55,7 @@ tusb_desc_device_t const desc_device =
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -82,8 +85,6 @@ enum
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
|
||||
@ -114,10 +115,12 @@ enum
|
||||
|
||||
#endif
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
@ -127,10 +130,13 @@ uint8_t const desc_fs_configuration[] =
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// high speed configuration
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
@ -138,7 +144,54 @@ uint8_t const desc_hs_configuration[] =
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
};
|
||||
#endif
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
// Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
|
||||
memcpy(desc_other_speed_config,
|
||||
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
|
||||
CONFIG_TOTAL_LEN);
|
||||
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
|
@ -26,13 +26,15 @@
|
||||
/*
|
||||
* After device is enumerated in dfu mode run the following commands
|
||||
*
|
||||
* To transfer firmware from host to device:
|
||||
* To transfer firmware from host to device (best to test with text file)
|
||||
*
|
||||
* $ dfu-util -D [filename]
|
||||
* $ dfu-util -d cafe -a 0 -D [filename]
|
||||
* $ dfu-util -d cafe -a 1 -D [filename]
|
||||
*
|
||||
* To transfer firmware from device to host:
|
||||
*
|
||||
* $ dfu-util -U [filename]
|
||||
* $ dfu-util -d cafe -a 0 -U [filename]
|
||||
* $ dfu-util -d cafe -a 1 -U [filename]
|
||||
*
|
||||
*/
|
||||
|
||||
@ -43,22 +45,21 @@
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
#ifndef DFU_VERBOSE
|
||||
#define DFU_VERBOSE 0
|
||||
#endif
|
||||
const char* upload_image[2]=
|
||||
{
|
||||
"Hello world from TinyUSB DFU! - Partition 0",
|
||||
"Hello world from TinyUSB DFU! - Partition 1"
|
||||
};
|
||||
|
||||
/* Blink pattern
|
||||
* - 1000 ms : device should reboot
|
||||
* - 250 ms : device not mounted
|
||||
* - 1000 ms : device mounted
|
||||
* - 2500 ms : device is suspended
|
||||
*/
|
||||
enum {
|
||||
BLINK_DFU_MODE = 100,
|
||||
BLINK_NOT_MOUNTED = 250,
|
||||
BLINK_MOUNTED = 1000,
|
||||
BLINK_SUSPENDED = 2500,
|
||||
@ -115,58 +116,89 @@ void tud_resume_cb(void)
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
// Invoked on DFU_DETACH request to reboot to the bootloader
|
||||
void tud_dfu_runtime_reboot_to_dfu_cb(void)
|
||||
//--------------------------------------------------------------------+
|
||||
// DFU callbacks
|
||||
// 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)
|
||||
{
|
||||
blink_interval_ms = BLINK_DFU_MODE;
|
||||
if ( state == DFU_DNBUSY )
|
||||
{
|
||||
// For this example
|
||||
// - Atl0 Flash is fast : 1 ms
|
||||
// - Alt1 EEPROM is slow: 100 ms
|
||||
return (alt == 0) ? 1 : 100;
|
||||
}
|
||||
else if (state == DFU_MANIFEST)
|
||||
{
|
||||
// since we don't buffer entire image and do any flashing in manifest stage
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_dfu_firmware_valid_check_cb(void)
|
||||
// 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)
|
||||
{
|
||||
printf(" Firmware check\r\n");
|
||||
return true;
|
||||
}
|
||||
(void) alt;
|
||||
(void) block_num;
|
||||
|
||||
void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length)
|
||||
{
|
||||
(void) data;
|
||||
printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length);
|
||||
//printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length);
|
||||
|
||||
#if DFU_VERBOSE
|
||||
for(uint16_t i=0; i<length; i++)
|
||||
{
|
||||
printf(" [%u][%u]: %x\r\n", wBlockNum, i, (uint8_t)data[i]);
|
||||
printf("%c", data[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
tud_dfu_dnload_complete();
|
||||
// flashing op for download complete without error
|
||||
tud_dfu_finish_flashing(DFU_STATUS_OK);
|
||||
}
|
||||
|
||||
bool tud_dfu_device_data_done_check_cb(void)
|
||||
// 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)
|
||||
{
|
||||
printf(" Host said no more data... Returning true\r\n");
|
||||
return true;
|
||||
(void) alt;
|
||||
printf("Download completed, enter manifestation\r\n");
|
||||
|
||||
// flashing op for manifest is complete without error
|
||||
// Application can perform checksum, should it fail, use appropriate status such as errVERIFY.
|
||||
tud_dfu_finish_flashing(DFU_STATUS_OK);
|
||||
}
|
||||
|
||||
void tud_dfu_abort_cb(void)
|
||||
{
|
||||
printf(" Host aborted transfer\r\n");
|
||||
}
|
||||
|
||||
#define UPLOAD_SIZE (29)
|
||||
const uint8_t upload_test[UPLOAD_SIZE] = "Hello world from TinyUSB DFU!";
|
||||
|
||||
uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length)
|
||||
// Invoked when received DFU_UPLOAD request
|
||||
// Application must populate data with up to length bytes and
|
||||
// Return the number of written bytes
|
||||
uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length)
|
||||
{
|
||||
(void) block_num;
|
||||
(void) length;
|
||||
|
||||
memcpy(data, upload_test, UPLOAD_SIZE);
|
||||
uint16_t const xfer_len = (uint16_t) strlen(upload_image[alt]);
|
||||
memcpy(data, upload_image[alt], xfer_len);
|
||||
|
||||
return UPLOAD_SIZE;
|
||||
return xfer_len;
|
||||
}
|
||||
|
||||
// Invoked when the Host has terminated a download or upload transfer
|
||||
void tud_dfu_abort_cb(uint8_t alt)
|
||||
{
|
||||
(void) alt;
|
||||
printf("Host aborted transfer\r\n");
|
||||
}
|
||||
|
||||
// Invoked when a DFU_DETACH request is received
|
||||
void tud_dfu_detach_cb(void)
|
||||
{
|
||||
printf("Host detach, we should probably reboot\r\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -76,12 +76,11 @@
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_DFU 1
|
||||
|
||||
#define CFG_TUD_DFU_RUNTIME 0
|
||||
#define CFG_TUD_DFU_MODE 1
|
||||
// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR
|
||||
#define CFG_TUD_DFU_XFER_BUFSIZE 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -81,23 +81,26 @@ uint8_t const * tud_descriptor_device_cb(void)
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Number of Alternate Interface (each for 1 flash partition)
|
||||
#define ALT_COUNT 2
|
||||
|
||||
enum
|
||||
{
|
||||
ITF_NUM_DFU_MODE,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN)
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT))
|
||||
|
||||
#define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK)
|
||||
#define FUNC_ATTRS (DFU_ATTR_CAN_UPLOAD | DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, attributes, detach timeout, transfer size */
|
||||
TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE),
|
||||
// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size
|
||||
TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE),
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
@ -120,7 +123,8 @@ char const* string_desc_arr [] =
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
"TinyUSB DFU", // 4: DFU
|
||||
"FLASH", // 4: DFU Partition 1
|
||||
"EEPROM", // 5: DFU Partition 2
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
@ -92,7 +92,7 @@ enum
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, attributes, detach timeout, transfer size */
|
||||
TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096),
|
||||
|
@ -178,6 +178,9 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
@ -190,6 +193,9 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
@ -208,7 +214,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
|
||||
// read10 & write10 has their own callback and MUST not be handled here
|
||||
|
||||
void const* response = NULL;
|
||||
uint16_t resplen = 0;
|
||||
int32_t resplen = 0;
|
||||
|
||||
// most scsi handled is input
|
||||
bool in_xfer = true;
|
||||
|
@ -160,7 +160,7 @@ enum
|
||||
uint8_t const desc_configuration_0[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_0_NUM_TOTAL, 0, CONFIG_0_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_0_NUM_TOTAL, 0, CONFIG_0_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_0_NUM_CDC, 0, EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC_OUT, EPNUM_0_CDC_IN, 64),
|
||||
@ -173,7 +173,7 @@ uint8_t const desc_configuration_0[] =
|
||||
uint8_t const desc_configuraiton_1[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_1_NUM_TOTAL, 0, CONFIG_1_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_1_NUM_MSC, 0, EPNUM_1_MSC_OUT, EPNUM_1_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64),
|
||||
|
28
examples/device/hid_boot_interface/CMakeLists.txt
Normal file
28
examples/device/hid_boot_interface/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT})
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_device_example(${PROJECT})
|
15
examples/device/hid_boot_interface/Makefile
Normal file
15
examples/device/hid_boot_interface/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE += \
|
||||
src/main.c \
|
||||
src/usb_descriptors.c
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../rules.mk
|
255
examples/device/hid_boot_interface/src/main.c
Normal file
255
examples/device/hid_boot_interface/src/main.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* Blink pattern
|
||||
* - 250 ms : device not mounted
|
||||
* - 1000 ms : device mounted
|
||||
* - 2500 ms : device is suspended
|
||||
*/
|
||||
enum {
|
||||
BLINK_NOT_MOUNTED = 250,
|
||||
BLINK_MOUNTED = 1000,
|
||||
BLINK_SUSPENDED = 2500,
|
||||
};
|
||||
|
||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
|
||||
void led_blinking_task(void);
|
||||
void hid_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
tusb_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
tud_task(); // tinyusb device task
|
||||
led_blinking_task();
|
||||
|
||||
hid_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Invoked when usb bus is resumed
|
||||
void tud_resume_cb(void)
|
||||
{
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB HID
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..)
|
||||
// tud_hid_report_complete_cb() is used to send the next report after previous one is complete
|
||||
void hid_task(void)
|
||||
{
|
||||
// Poll every 10ms
|
||||
const uint32_t interval_ms = 10;
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
uint32_t const btn = board_button_read();
|
||||
|
||||
if ( tud_suspended() && btn )
|
||||
{
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
tud_remote_wakeup();
|
||||
}
|
||||
else
|
||||
{
|
||||
// keyboard interface
|
||||
if ( tud_hid_n_ready(ITF_NUM_KEYBOARD) )
|
||||
{
|
||||
// used to avoid send multiple consecutive zero report for keyboard
|
||||
static bool has_keyboard_key = false;
|
||||
|
||||
uint8_t const report_id = 0;
|
||||
uint8_t const modifier = 0;
|
||||
|
||||
if ( btn )
|
||||
{
|
||||
uint8_t keycode[6] = { 0 };
|
||||
keycode[0] = HID_KEY_ARROW_RIGHT;
|
||||
|
||||
tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, keycode);
|
||||
has_keyboard_key = true;
|
||||
}else
|
||||
{
|
||||
// send empty key report if previously has key pressed
|
||||
if (has_keyboard_key) tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, NULL);
|
||||
has_keyboard_key = false;
|
||||
}
|
||||
}
|
||||
|
||||
// mouse interface
|
||||
if ( tud_hid_n_ready(ITF_NUM_MOUSE) )
|
||||
{
|
||||
if ( btn )
|
||||
{
|
||||
uint8_t const report_id = 0;
|
||||
uint8_t const button_mask = 0;
|
||||
uint8_t const veritical = 0;
|
||||
uint8_t const horizontal = 0;
|
||||
int8_t const delta = 5;
|
||||
|
||||
tud_hid_n_mouse_report(ITF_NUM_MOUSE, report_id, button_mask, delta, delta, veritical, horizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received SET_PROTOCOL request
|
||||
// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
|
||||
void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol)
|
||||
{
|
||||
(void) instance;
|
||||
(void) protocol;
|
||||
|
||||
// nothing to do since we use the same compatible boot report for both Boot and Report mode.
|
||||
// TOOD set a indicator for user
|
||||
}
|
||||
|
||||
// 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
|
||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len)
|
||||
{
|
||||
(void) instance;
|
||||
(void) report;
|
||||
(void) len;
|
||||
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// TODO not Implemented
|
||||
(void) instance;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) reqlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
(void) report_id;
|
||||
|
||||
// keyboard interface
|
||||
if (instance == ITF_NUM_KEYBOARD)
|
||||
{
|
||||
// Set keyboard LED e.g Capslock, Numlock etc...
|
||||
if (report_type == HID_REPORT_TYPE_OUTPUT)
|
||||
{
|
||||
// bufsize should be (at least) 1
|
||||
if ( bufsize < 1 ) return;
|
||||
|
||||
uint8_t const kbd_leds = buffer[0];
|
||||
|
||||
if (kbd_leds & KEYBOARD_LED_CAPSLOCK)
|
||||
{
|
||||
// Capslock On: disable blink, turn led on
|
||||
blink_interval_ms = 0;
|
||||
board_led_write(true);
|
||||
}else
|
||||
{
|
||||
// Caplocks Off: back to normal blink
|
||||
board_led_write(false);
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// BLINKING TASK
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// blink is disabled
|
||||
if (!blink_interval_ms) return;
|
||||
|
||||
// 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
|
||||
}
|
111
examples/device/hid_boot_interface/src/tusb_config.h
Normal file
111
examples/device/hid_boot_interface/src/tusb_config.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by board.mk
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
// RHPort number used for device can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_DEVICE_RHPORT_NUM
|
||||
#define BOARD_DEVICE_RHPORT_NUM 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Device mode with rhport and speed defined by board.mk
|
||||
#if BOARD_DEVICE_RHPORT_NUM == 0
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#elif BOARD_DEVICE_RHPORT_NUM == 1
|
||||
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#else
|
||||
#error "Incorrect RHPort configuration"
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
#endif
|
||||
|
||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
|
||||
// #define CFG_TUSB_DEBUG 0
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 2 // 1 for boot keyboard, 1 for boot mouse
|
||||
#define CFG_TUD_CDC 0
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_EP_BUFSIZE 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
180
examples/device/hid_boot_interface/src/usb_descriptors.c
Normal file
180
examples/device/hid_boot_interface/src/usb_descriptors.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||
*
|
||||
* Auto ProductID layout's Bitmap:
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const * tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *) &desc_device;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Report Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint8_t const desc_hid_keyboard_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
};
|
||||
|
||||
uint8_t const desc_hid_mouse_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_MOUSE()
|
||||
};
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance)
|
||||
{
|
||||
return (instance == 0) ? desc_hid_keyboard_report : desc_hid_mouse_report;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2*TUD_HID_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt, 5 Bulk etc ...
|
||||
#define EPNUM_KEYBOARD 0x81
|
||||
#define EPNUM_MOUSE 0x84
|
||||
#else
|
||||
#define EPNUM_KEYBOARD 0x81
|
||||
#define EPNUM_MOUSE 0x82
|
||||
#endif
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_keyboard_report), EPNUM_KEYBOARD, CFG_TUD_HID_EP_BUFSIZE, 10),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_MOUSE, 0, HID_ITF_PROTOCOL_MOUSE, sizeof(desc_hid_mouse_report), EPNUM_MOUSE, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const* string_desc_arr [] =
|
||||
{
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
(void) langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0)
|
||||
{
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = strlen(str);
|
||||
if ( chr_count > 31 ) chr_count = 31;
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for(uint8_t i=0; i<chr_count; i++)
|
||||
{
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||
|
||||
return _desc_str;
|
||||
}
|
35
examples/device/hid_boot_interface/src/usb_descriptors.h
Normal file
35
examples/device/hid_boot_interface/src/usb_descriptors.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef USB_DESCRIPTORS_H_
|
||||
#define USB_DESCRIPTORS_H_
|
||||
|
||||
enum
|
||||
{
|
||||
ITF_NUM_KEYBOARD,
|
||||
ITF_NUM_MOUSE,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#endif
|
@ -223,9 +223,9 @@ void hid_task(void)
|
||||
// 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
|
||||
void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
|
||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len)
|
||||
{
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
(void) len;
|
||||
|
||||
uint8_t next_report_id = report[0] + 1;
|
||||
@ -239,10 +239,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
|
||||
// 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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||
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)
|
||||
{
|
||||
// TODO not Implemented
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
@ -253,14 +253,33 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
|
||||
|
||||
// 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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
||||
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)
|
||||
{
|
||||
// TODO set LED based on CAPLOCK, NUMLOCK etc...
|
||||
(void) itf;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
(void) instance;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_OUTPUT)
|
||||
{
|
||||
// Set keyboard LED e.g Capslock, Numlock etc...
|
||||
if (report_id == REPORT_ID_KEYBOARD)
|
||||
{
|
||||
// bufsize should be (at least) 1
|
||||
if ( bufsize < 1 ) return;
|
||||
|
||||
uint8_t const kbd_leds = buffer[0];
|
||||
|
||||
if (kbd_leds & KEYBOARD_LED_CAPSLOCK)
|
||||
{
|
||||
// Capslock On: disable blink, turn led on
|
||||
blink_interval_ms = 0;
|
||||
board_led_write(true);
|
||||
}else
|
||||
{
|
||||
// Caplocks Off: back to normal blink
|
||||
board_led_write(false);
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -271,6 +290,9 @@ void led_blinking_task(void)
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// blink is disabled
|
||||
if (!blink_interval_ms) return;
|
||||
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
|
||||
start_ms += blink_interval_ms;
|
||||
|
@ -48,7 +48,7 @@
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -82,9 +85,9 @@ uint8_t const desc_hid_report[] =
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance)
|
||||
{
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
return desc_hid_report;
|
||||
}
|
||||
|
||||
@ -111,12 +114,62 @@ uint8_t const desc_configuration[] =
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// other speed config is basically configuration with type = OHER_SPEED_CONFIG
|
||||
memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
// this example use the same configuration for both high and full speed mode
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// This example use the same configuration for both high and full speed mode
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
|
@ -154,11 +154,14 @@ extern uint32_t SystemCoreClock;
|
||||
//--------------------------------------------------------------------+
|
||||
// Interrupt nesting behavior configuration.
|
||||
//--------------------------------------------------------------------+
|
||||
/* Cortex-M specific definitions. __NVIC_PRIO_BITS is defined in core_cmx.h */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
#if defined(__NVIC_PRIO_BITS)
|
||||
// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#elif defined(__ECLIC_INTCTLBITS)
|
||||
// RISC-V Bumblebee core from nuclei
|
||||
#define configPRIO_BITS __ECLIC_INTCTLBITS
|
||||
#else
|
||||
#error "This port requires __NVIC_PRIO_BITS to be defined"
|
||||
#error "FreeRTOS configPRIO_BITS to be defined"
|
||||
#endif
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
|
||||
|
@ -94,7 +94,7 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RX63X
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X
|
||||
#include "iodefine.h"
|
||||
void vApplicationSetupTimerInterrupt(void)
|
||||
{
|
||||
|
@ -282,9 +282,9 @@ void hid_task(void* param)
|
||||
// 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
|
||||
void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
|
||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len)
|
||||
{
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
(void) len;
|
||||
|
||||
uint8_t next_report_id = report[0] + 1;
|
||||
@ -299,10 +299,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
|
||||
// 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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||
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)
|
||||
{
|
||||
// TODO not Implemented
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
@ -313,14 +313,33 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
|
||||
|
||||
// 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 itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
||||
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)
|
||||
{
|
||||
// TODO set LED based on CAPLOCK, NUMLOCK etc...
|
||||
(void) itf;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
(void) instance;
|
||||
|
||||
if (report_type == HID_REPORT_TYPE_OUTPUT)
|
||||
{
|
||||
// Set keyboard LED e.g Capslock, Numlock etc...
|
||||
if (report_id == REPORT_ID_KEYBOARD)
|
||||
{
|
||||
// bufsize should be (at least) 1
|
||||
if ( bufsize < 1 ) return;
|
||||
|
||||
uint8_t const kbd_leds = buffer[0];
|
||||
|
||||
if (kbd_leds & KEYBOARD_LED_CAPSLOCK)
|
||||
{
|
||||
// Capslock On: disable blink, turn led on
|
||||
xTimerStop(blinky_tm, portMAX_DELAY);
|
||||
board_led_write(true);
|
||||
}else
|
||||
{
|
||||
// Caplocks Off: back to normal blink
|
||||
board_led_write(false);
|
||||
xTimerStart(blinky_tm, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -67,8 +67,9 @@
|
||||
// This examples use FreeRTOS
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
|
||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
|
||||
// #define CFG_TUSB_DEBUG 0
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@ -43,13 +46,13 @@ tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bcdUSB = USB_BCD,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
@ -82,9 +85,9 @@ uint8_t const desc_hid_report[] =
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance)
|
||||
{
|
||||
(void) itf;
|
||||
(void) instance;
|
||||
return desc_hid_report;
|
||||
}
|
||||
|
||||
@ -111,6 +114,54 @@ uint8_t const desc_configuration[] =
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// other speed config is basically configuration with type = OHER_SPEED_CONFIG
|
||||
memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);
|
||||
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
|
||||
|
||||
// this example use the same configuration for both high and full speed mode
|
||||
return desc_other_speed_config;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
|
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
"Feather_nRF52840":[0X239A,0X8029],
|
||||
"Metro_nRF52840":[0X239A,0X803F],
|
||||
}
|
||||
"Adafruit Boards":[0x239A,0xFFFF],
|
||||
"TinyUSB example":[0xCAFE,0xFFFF]
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ var HID = require('node-hid');
|
||||
var os = require('os')
|
||||
// list of supported devices
|
||||
var boards = require('./boards.js')
|
||||
|
||||
var isWin = (os.platform() === 'win32');
|
||||
var devices = HID.devices();
|
||||
|
||||
// this will choose any device found in the boards.js file
|
||||
@ -19,10 +17,8 @@ var message = "Hello World!"
|
||||
// This means if you have characters in your string that are not Latin-1 you will have to add additional logic for character codes above 255
|
||||
var messageBuffer = Array.from(message, function(c){return c.charCodeAt(0)});
|
||||
|
||||
// Windows wants you to prepend a 0 to whatever you send
|
||||
if(isWin){
|
||||
messageBuffer.unshift(0)
|
||||
}
|
||||
// HIDAPI requires us to prepend a 0 for single hid report as dummy reportID
|
||||
messageBuffer.unshift(0)
|
||||
|
||||
// Some OSes expect that you always send a buffer that equals your report length
|
||||
// So lets fill up the rest of the buffer with zeros
|
||||
@ -66,6 +62,7 @@ function anySupportedBoard(d) {
|
||||
|
||||
|
||||
function isDevice(board,d){
|
||||
return d.vendorId==board[0] && d.productId==board[1];
|
||||
// product id 0xff is matches all
|
||||
return d.vendorId==board[0] && (d.productId==board[1] || board[1] == 0xFFFF);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,10 @@ for dict in hid.enumerate(USB_VID):
|
||||
if dev:
|
||||
while True:
|
||||
# Get input from console and encode to UTF8 for array of chars.
|
||||
str_out = input("Send text to HID Device : ").encode('utf-8')
|
||||
# hid generic inout is single report therefore by HIDAPI requirement
|
||||
# it must be preceeded with 0x00 as dummy reportID
|
||||
str_out = b'\x00'
|
||||
str_out += input("Send text to HID Device : ").encode('utf-8')
|
||||
dev.write(str_out)
|
||||
str_in = dev.read(64)
|
||||
print("Received from HID Device:", str_in, '\n')
|
||||
|
@ -36,16 +36,24 @@
|
||||
*
|
||||
* There are 2 ways to test the sketch
|
||||
* 1. Using nodejs
|
||||
* - Install nodejs and npm to your PC
|
||||
* - Install excellent node-hid (https://github.com/node-hid/node-hid) by
|
||||
* $ npm install node-hid
|
||||
* - Run provided hid test script
|
||||
* $ node hid_test.js
|
||||
* - Install nodejs and npm to your PC
|
||||
*
|
||||
* 2. Using python hidRun
|
||||
* - Python and `hid` package is required, for installation please follow https://pypi.org/project/hid/
|
||||
* - Run provided hid test script to send and receive data to this device.
|
||||
* $ python3 hid_test.py
|
||||
* - Install excellent node-hid (https://github.com/node-hid/node-hid) by
|
||||
* $ npm install node-hid
|
||||
*
|
||||
* - Run provided hid test script
|
||||
* $ node hid_test.js
|
||||
*
|
||||
* 2. Using python
|
||||
* - Install `hid` package (https://pypi.org/project/hid/) by
|
||||
* $ pip install hid
|
||||
*
|
||||
* - hid package replies on hidapi (https://github.com/libusb/hidapi) for backend,
|
||||
* which already available in Linux. However on windows, you may need to download its dlls from their release page and
|
||||
* copy it over to folder where python is installed.
|
||||
*
|
||||
* - Run provided hid test script to send and receive data to this device.
|
||||
* $ python3 hid_test.py
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -101,7 +101,7 @@ enum
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||
|
@ -134,7 +134,7 @@ void midi_task(void)
|
||||
uint8_t packet[4];
|
||||
while ( tud_midi_available() ) tud_midi_packet_read(packet);
|
||||
|
||||
// send note every 1000 ms
|
||||
// send note periodically
|
||||
if (board_millis() - start_ms < 286) return; // not enough time
|
||||
start_ms += 286;
|
||||
|
||||
|
@ -91,7 +91,7 @@ enum
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
|
||||
@ -101,7 +101,7 @@ uint8_t const desc_fs_configuration[] =
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 512)
|
||||
|
@ -268,16 +268,33 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo
|
||||
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
|
||||
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
uint8_t const* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
bool tud_msc_is_writable_cb (uint8_t lun)
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Callback invoked when received WRITE10 command.
|
||||
// Process data in buffer to disk's storage and return number of written bytes
|
||||
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
@ -296,7 +313,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
|
||||
// read10 & write10 has their own callback and MUST not be handled here
|
||||
|
||||
void const* response = NULL;
|
||||
uint16_t resplen = 0;
|
||||
int32_t resplen = 0;
|
||||
|
||||
// most scsi handled is input
|
||||
bool in_xfer = true;
|
||||
|
@ -99,7 +99,7 @@ enum
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
|
||||
@ -109,7 +109,7 @@ uint8_t const desc_fs_configuration[] =
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
|
@ -178,21 +178,10 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size)
|
||||
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg)
|
||||
{
|
||||
struct pbuf *p = (struct pbuf *)ref;
|
||||
struct pbuf *q;
|
||||
uint16_t len = 0;
|
||||
|
||||
(void)arg; /* unused for this example */
|
||||
|
||||
/* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
memcpy(dst, (char *)q->payload, q->len);
|
||||
dst += q->len;
|
||||
len += q->len;
|
||||
if (q->len == q->tot_len) break;
|
||||
}
|
||||
|
||||
return len;
|
||||
return pbuf_copy_partial(p, dst, p->tot_len, 0);
|
||||
}
|
||||
|
||||
static void service_traffic(void)
|
||||
|
@ -107,8 +107,8 @@ uint8_t const * tud_descriptor_device_cb(void)
|
||||
#define EPNUM_NET_OUT 0x02
|
||||
#define EPNUM_NET_IN 0x82
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG
|
||||
// SAMG doesn't support a same endpoint number with different direction IN and OUT
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_NET_NOTIF 0x81
|
||||
#define EPNUM_NET_OUT 0x02
|
||||
|
0
examples/device/uac2_headset/.skip.MCU_LPC11UXX
Normal file
0
examples/device/uac2_headset/.skip.MCU_LPC11UXX
Normal file
0
examples/device/uac2_headset/.skip.MCU_LPC13XX
Normal file
0
examples/device/uac2_headset/.skip.MCU_LPC13XX
Normal file
0
examples/device/uac2_headset/.skip.MCU_NUC121
Normal file
0
examples/device/uac2_headset/.skip.MCU_NUC121
Normal file
@ -34,9 +34,15 @@
|
||||
// MACRO CONSTANT TYPEDEF PROTOTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef AUDIO_SAMPLE_RATE
|
||||
#define AUDIO_SAMPLE_RATE 48000
|
||||
// List of supported sample rates
|
||||
#if defined(__RX__)
|
||||
const uint32_t sample_rates[] = {44100, 48000};
|
||||
#else
|
||||
const uint32_t sample_rates[] = {44100, 48000, 88200, 96000};
|
||||
#endif
|
||||
uint32_t current_sample_rate = 44100;
|
||||
|
||||
#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates)
|
||||
|
||||
/* Blink pattern
|
||||
* - 25 ms : streaming data
|
||||
@ -76,11 +82,16 @@ int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master chan
|
||||
int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0
|
||||
|
||||
// Buffer for microphone data
|
||||
int16_t mic_buf[1000];
|
||||
int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4];
|
||||
// Buffer for speaker data
|
||||
int16_t spk_buf[1000];
|
||||
int32_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4];
|
||||
// Speaker data size received in the last frame
|
||||
int spk_data_size;
|
||||
// Resolution per format
|
||||
const uint8_t resolutions_per_format[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] = {CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX,
|
||||
CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX};
|
||||
// Current resolution, update on format change
|
||||
uint8_t current_resolution;
|
||||
|
||||
void led_blinking_task(void);
|
||||
void audio_task(void);
|
||||
@ -135,55 +146,35 @@ void tud_resume_cb(void)
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Helper for clock get requests
|
||||
static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request)
|
||||
{
|
||||
TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
|
||||
|
||||
// Example supports only single frequency, same value will be used for current value and range
|
||||
if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
|
||||
{
|
||||
if (request->bRequest == AUDIO_CS_REQ_CUR)
|
||||
{
|
||||
TU_LOG2("Clock get current freq %u\r\n", AUDIO_SAMPLE_RATE);
|
||||
TU_LOG1("Clock get current freq %u\r\n", current_sample_rate);
|
||||
|
||||
audio_control_cur_4_t curf = { tu_htole32(AUDIO_SAMPLE_RATE) };
|
||||
audio_control_cur_4_t curf = { tu_htole32(current_sample_rate) };
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf));
|
||||
}
|
||||
else if (request->bRequest == AUDIO_CS_REQ_RANGE)
|
||||
{
|
||||
audio_control_range_4_n_t(1) rangef =
|
||||
audio_control_range_4_n_t(N_SAMPLE_RATES) rangef =
|
||||
{
|
||||
.wNumSubRanges = tu_htole16(1),
|
||||
.subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0}
|
||||
.wNumSubRanges = tu_htole16(N_SAMPLE_RATES)
|
||||
};
|
||||
TU_LOG2("Clock get freq range (%d, %d, %d)\r\n", (int)rangef.subrange[0].bMin, (int)rangef.subrange[0].bMax, (int)rangef.subrange[0].bRes);
|
||||
TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES);
|
||||
for(uint8_t i = 0; i < N_SAMPLE_RATES; i++)
|
||||
{
|
||||
rangef.subrange[i].bMin = sample_rates[i];
|
||||
rangef.subrange[i].bMax = sample_rates[i];
|
||||
rangef.subrange[i].bRes = 0;
|
||||
TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes);
|
||||
}
|
||||
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef));
|
||||
}
|
||||
}
|
||||
@ -191,7 +182,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
|
||||
request->bRequest == AUDIO_CS_REQ_CUR)
|
||||
{
|
||||
audio_control_cur_1_t cur_valid = { .bCur = 1 };
|
||||
TU_LOG2("Clock get is valid %u\r\n", cur_valid.bCur);
|
||||
TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur);
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid));
|
||||
}
|
||||
TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n",
|
||||
@ -199,6 +190,32 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper for clock set requests
|
||||
static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK);
|
||||
TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR);
|
||||
|
||||
if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ)
|
||||
{
|
||||
TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t));
|
||||
|
||||
current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur;
|
||||
|
||||
TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n",
|
||||
request->bEntityID, request->bControlSelector, request->bRequest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for feature unit get requests
|
||||
static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request)
|
||||
{
|
||||
@ -207,7 +224,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
|
||||
if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR)
|
||||
{
|
||||
audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] };
|
||||
TU_LOG2("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
|
||||
TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur);
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1));
|
||||
}
|
||||
else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME)
|
||||
@ -218,14 +235,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req
|
||||
.wNumSubRanges = tu_htole16(1),
|
||||
.subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) }
|
||||
};
|
||||
TU_LOG2("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
|
||||
TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber,
|
||||
range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256);
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol));
|
||||
}
|
||||
else if (request->bRequest == AUDIO_CS_REQ_CUR)
|
||||
{
|
||||
audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) };
|
||||
TU_LOG2("Get channel %u volume %u dB\r\n", request->bChannelNumber, cur_vol.bCur);
|
||||
TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256);
|
||||
return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol));
|
||||
}
|
||||
}
|
||||
@ -249,7 +266,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
|
||||
|
||||
mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur;
|
||||
|
||||
TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
|
||||
TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -259,7 +276,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req
|
||||
|
||||
volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur;
|
||||
|
||||
TU_LOG2("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
|
||||
TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -299,7 +316,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p
|
||||
|
||||
if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT)
|
||||
return tud_audio_feature_unit_set_request(rhport, request, buf);
|
||||
|
||||
if (request->bEntityID == UAC2_ENTITY_CLOCK)
|
||||
return tud_audio_clock_set_request(rhport, request, buf);
|
||||
TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n",
|
||||
request->bEntityID, request->bControlSelector, request->bRequest);
|
||||
|
||||
@ -329,6 +347,13 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque
|
||||
if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0)
|
||||
blink_interval_ms = BLINK_STREAMING;
|
||||
|
||||
// Clear buffer when streaming format is changed
|
||||
spk_data_size = 0;
|
||||
if(alt != 0)
|
||||
{
|
||||
current_resolution = resolutions_per_format[alt-1];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -362,20 +387,40 @@ void audio_task(void)
|
||||
{
|
||||
// When new data arrived, copy data from speaker buffer, to microphone buffer
|
||||
// and send it over
|
||||
// Only support speaker & headphone both have the same resolution
|
||||
// If one is 16bit another is 24bit be care of LOUD noise !
|
||||
if (spk_data_size)
|
||||
{
|
||||
int16_t *src = spk_buf;
|
||||
int16_t *limit = spk_buf + spk_data_size / 2;
|
||||
int16_t *dst = mic_buf;
|
||||
while (src < limit)
|
||||
if (current_resolution == 16)
|
||||
{
|
||||
// Combine two channels into one
|
||||
int32_t left = *src++;
|
||||
int32_t right = *src++;
|
||||
*dst++ = (int16_t)((left + right) / 2);
|
||||
int16_t *src = (int16_t*)spk_buf;
|
||||
int16_t *limit = (int16_t*)spk_buf + spk_data_size / 2;
|
||||
int16_t *dst = (int16_t*)mic_buf;
|
||||
while (src < limit)
|
||||
{
|
||||
// Combine two channels into one
|
||||
int32_t left = *src++;
|
||||
int32_t right = *src++;
|
||||
*dst++ = (left >> 1) + (right >> 1);
|
||||
}
|
||||
tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2);
|
||||
spk_data_size = 0;
|
||||
}
|
||||
else if (current_resolution == 24)
|
||||
{
|
||||
int32_t *src = spk_buf;
|
||||
int32_t *limit = spk_buf + spk_data_size / 4;
|
||||
int32_t *dst = mic_buf;
|
||||
while (src < limit)
|
||||
{
|
||||
// Combine two channels into one
|
||||
int32_t left = *src++;
|
||||
int32_t right = *src++;
|
||||
*dst++ = ((left >> 1) + (right >> 1)) & 0xffffff00;
|
||||
}
|
||||
tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2);
|
||||
spk_data_size = 0;
|
||||
}
|
||||
tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2);
|
||||
spk_data_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,33 +93,61 @@ extern "C" {
|
||||
//--------------------------------------------------------------------
|
||||
// AUDIO CLASS DRIVER CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO)
|
||||
#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO)
|
||||
|
||||
//#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN 220 // This equals TUD_AUDIO_HEADSET_STEREO_DESC_LEN, however, including it from usb_descriptors.h is not possible due to some strange include hassle
|
||||
#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN
|
||||
#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN
|
||||
|
||||
// How many formats are used, need to adjust USB descriptor if changed
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2
|
||||
|
||||
// Audio format type I specifications
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2
|
||||
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0
|
||||
#if defined(__RX__)
|
||||
#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 // 16bit/48kHz is the best quality for Renesas RX
|
||||
#else
|
||||
#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000 // 24bit/96kHz is the best quality for full-speed, high-speed is needed beyond this
|
||||
#endif
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2
|
||||
|
||||
// 16bit in 16bit slots
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX 2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX 16
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX 2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
|
||||
|
||||
#if defined(__RX__)
|
||||
// 8bit in 8bit slots
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 8
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 8
|
||||
#else
|
||||
// 24bit in 32bit slots
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 24
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 4
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24
|
||||
#endif
|
||||
|
||||
// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense)
|
||||
#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
|
||||
#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used
|
||||
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
|
||||
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN)*2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used
|
||||
|
||||
// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense)
|
||||
#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1
|
||||
#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_OUT_SZ // Maximum EP IN size for all AS alternate settings used
|
||||
|
||||
#define CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
|
||||
#define CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX)
|
||||
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used
|
||||
|
||||
// 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 - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes)
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2
|
||||
|
||||
// Size of control request buffer
|
||||
#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64
|
||||
|
@ -79,21 +79,29 @@ uint8_t const * tud_descriptor_device_cb(void)
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
|
||||
#define EPNUM_AUDIO 0x03
|
||||
#define EPNUM_AUDIO_IN 0x03
|
||||
#define EPNUM_AUDIO_OUT 0x03
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
|
||||
// ISO endpoints for NRF5x are fixed to 0x08 (0x88)
|
||||
#define EPNUM_AUDIO 0x08
|
||||
#define EPNUM_AUDIO_IN 0x08
|
||||
#define EPNUM_AUDIO_OUT 0x08
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_AUDIO_IN 0x01
|
||||
#define EPNUM_AUDIO_OUT 0x02
|
||||
#else
|
||||
#define EPNUM_AUDIO 0x01
|
||||
#define EPNUM_AUDIO_IN 0x01
|
||||
#define EPNUM_AUDIO_OUT 0x01
|
||||
#endif
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN)
|
||||
TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80)
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
|
@ -55,21 +55,36 @@ enum
|
||||
+ TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
|
||||
+ TUD_AUDIO_DESC_INPUT_TERM_LEN\
|
||||
+ TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
|
||||
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
|
||||
/* Interface 1, Alternate 2 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
|
||||
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
|
||||
/* Interface 2, Alternate 0 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
/* Interface 2, Alternate 1 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
|
||||
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\
|
||||
/* Interface 2, Alternate 2 */\
|
||||
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_INT_LEN\
|
||||
+ TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\
|
||||
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
|
||||
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
|
||||
|
||||
|
||||
#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epin, _epinsize) \
|
||||
#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \
|
||||
/* Standard Interface Association Descriptor (IAD) */\
|
||||
TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\
|
||||
/* Standard AC Interface Descriptor(4.7.1) */\
|
||||
@ -77,13 +92,13 @@ enum
|
||||
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
|
||||
TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
|
||||
/* Clock Source Descriptor(4.7.2.1) */\
|
||||
TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 5, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \
|
||||
TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \
|
||||
/* Input Terminal Descriptor(4.7.2.4) */\
|
||||
TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
|
||||
/* Feature Unit Descriptor(4.7.2.8) */\
|
||||
TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrlch0master*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\
|
||||
/* Output Terminal Descriptor(4.7.2.5) */\
|
||||
TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
|
||||
TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
|
||||
/* Input Terminal Descriptor(4.7.2.4) */\
|
||||
TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
|
||||
/* Output Terminal Descriptor(4.7.2.5) */\
|
||||
@ -95,26 +110,46 @@ enum
|
||||
/* Interface 1, Alternate 1 - alternate interface for data streaming */\
|
||||
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\
|
||||
/* Class-Specific AS Interface Descriptor(4.9.2) */\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\
|
||||
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_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_MILLISEC, /*_lockdelay*/ 0x0001),\
|
||||
/* Interface 1, Alternate 2 - alternate interface for data streaming */\
|
||||
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\
|
||||
/* Class-Specific AS Interface Descriptor(4.9.2) */\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\
|
||||
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_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_MILLISEC, /*_lockdelay*/ 0x0001),\
|
||||
/* Standard AS Interface Descriptor(4.9.1) */\
|
||||
/* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\
|
||||
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\
|
||||
/* Standard AS Interface Descriptor(4.9.1) */\
|
||||
/* Interface 1, Alternate 1 - alternate interface for data streaming */\
|
||||
/* Interface 2, Alternate 1 - alternate interface for data streaming */\
|
||||
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\
|
||||
/* Class-Specific AS Interface Descriptor(4.9.2) */\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\
|
||||
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_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)\
|
||||
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),\
|
||||
/* Interface 2, Alternate 2 - alternate interface for data streaming */\
|
||||
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\
|
||||
/* Class-Specific AS Interface Descriptor(4.9.2) */\
|
||||
TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\
|
||||
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
|
||||
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\
|
||||
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
|
||||
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_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)
|
||||
|
||||
#endif
|
||||
|
@ -122,7 +122,7 @@ enum
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
TUD_USBTMC_DESC(ITF_NUM_USBTMC),
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ enum {
|
||||
|
||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
|
||||
#define URL "www.tinyusb.org/examples/webusb-serial"
|
||||
#define URL "example.tinyusb.org/webusb-serial/"
|
||||
|
||||
const tusb_desc_webusb_url_t desc_url =
|
||||
{
|
||||
|
@ -86,23 +86,34 @@ enum
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
|
||||
#define EPNUM_CDC 2
|
||||
#define EPNUM_VENDOR 5
|
||||
#define EPNUM_CDC_IN 2
|
||||
#define EPNUM_CDC_OUT 2
|
||||
#define EPNUM_VENDOR_IN 5
|
||||
#define EPNUM_VENDOR_OUT 5
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_CDC_IN 2
|
||||
#define EPNUM_CDC_OUT 3
|
||||
#define EPNUM_VENDOR_IN 4
|
||||
#define EPNUM_VENDOR_OUT 5
|
||||
#else
|
||||
#define EPNUM_CDC 2
|
||||
#define EPNUM_VENDOR 3
|
||||
#define EPNUM_CDC_IN 2
|
||||
#define EPNUM_CDC_OUT 2
|
||||
#define EPNUM_VENDOR_IN 3
|
||||
#define EPNUM_VENDOR_OUT 3
|
||||
#endif
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_OUT, 0x80 | EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64),
|
||||
|
||||
// Interface number, string index, EP Out & IN address, EP size
|
||||
TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR_OUT, 0x80 | EPNUM_VENDOR_IN, TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
|
@ -30,7 +30,8 @@
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// If your host terminal support ansi escape code, it can be use to simulate mouse cursor
|
||||
// If your host terminal support ansi escape code such as TeraTerm
|
||||
// it can be use to simulate mouse cursor movement within terminal
|
||||
#define USE_ANSI_ESCAPE 0
|
||||
|
||||
#define MAX_REPORT 4
|
||||
@ -38,11 +39,15 @@
|
||||
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
// Each HID instance can has multiple reports
|
||||
static uint8_t _report_count[CFG_TUH_HID];
|
||||
static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT];
|
||||
static struct
|
||||
{
|
||||
uint8_t report_count;
|
||||
tuh_hid_report_info_t report_info[MAX_REPORT];
|
||||
}hid_info[CFG_TUH_HID];
|
||||
|
||||
static void process_kbd_report(hid_keyboard_report_t const *report);
|
||||
static void process_mouse_report(hid_mouse_report_t const * report);
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||
|
||||
void hid_app_task(void)
|
||||
{
|
||||
@ -56,17 +61,32 @@ void hid_app_task(void)
|
||||
// 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
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
|
||||
|
||||
// Interface protocol
|
||||
const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t
|
||||
uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
// Interface protocol (hid_interface_protocol_enum_t)
|
||||
const char* protocol_str[] = { "None", "Keyboard", "Mouse" };
|
||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
|
||||
// Parse report descriptor with built-in parser
|
||||
_report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len);
|
||||
printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]);
|
||||
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
|
||||
|
||||
// By default host stack will use activate boot protocol on supported interface.
|
||||
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
|
||||
if ( itf_protocol == HID_ITF_PROTOCOL_NONE )
|
||||
{
|
||||
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
|
||||
printf("HID has %u reports \r\n", hid_info[instance].report_count);
|
||||
}
|
||||
|
||||
// request to receive report
|
||||
// tuh_hid_report_received_cb() will be invoked when report is available
|
||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||
{
|
||||
printf("Error: cannot request to receive report\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when device with hid interface is un-mounted
|
||||
@ -78,59 +98,30 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
||||
// Invoked when received report from device via interrupt endpoint
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
(void) dev_addr;
|
||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
|
||||
uint8_t const rpt_count = _report_count[instance];
|
||||
tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance];
|
||||
tuh_hid_report_info_t* rpt_info = NULL;
|
||||
|
||||
if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0)
|
||||
switch (itf_protocol)
|
||||
{
|
||||
// Simple report without report ID as 1st byte
|
||||
rpt_info = &rpt_info_arr[0];
|
||||
}else
|
||||
{
|
||||
// Composite report, 1st byte is report ID, data starts from 2nd byte
|
||||
uint8_t const rpt_id = report[0];
|
||||
case HID_ITF_PROTOCOL_KEYBOARD:
|
||||
TU_LOG2("HID receive boot keyboard report\r\n");
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
|
||||
// Find report id in the arrray
|
||||
for(uint8_t i=0; i<rpt_count; i++)
|
||||
{
|
||||
if (rpt_id == rpt_info_arr[i].report_id )
|
||||
{
|
||||
rpt_info = &rpt_info_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
case HID_ITF_PROTOCOL_MOUSE:
|
||||
TU_LOG2("HID receive boot mouse report\r\n");
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
|
||||
report++;
|
||||
len--;
|
||||
default:
|
||||
// Generic report requires matching ReportID and contents with previous parsed report info
|
||||
process_generic_report(dev_addr, instance, report, len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rpt_info)
|
||||
// continue to request to receive report
|
||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||
{
|
||||
printf("Couldn't find the report info for this report !\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP )
|
||||
{
|
||||
switch (rpt_info->usage)
|
||||
{
|
||||
case HID_USAGE_DESKTOP_KEYBOARD:
|
||||
TU_LOG1("HID receive keyboard report\r\n");
|
||||
// Assume keyboard follow boot report layout
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
|
||||
case HID_USAGE_DESKTOP_MOUSE:
|
||||
TU_LOG1("HID receive mouse report\r\n");
|
||||
// Assume mouse follow boot report layout
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
printf("Error: cannot request to receive report\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +155,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report)
|
||||
}else
|
||||
{
|
||||
// not existed in previous report means the current key is pressed
|
||||
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
|
||||
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
|
||||
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
|
||||
putchar(ch);
|
||||
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
|
||||
@ -235,3 +226,71 @@ static void process_mouse_report(hid_mouse_report_t const * report)
|
||||
//------------- cursor movement -------------//
|
||||
cursor_movement(report->x, report->y, report->wheel);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Generic Report
|
||||
//--------------------------------------------------------------------+
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
(void) dev_addr;
|
||||
|
||||
uint8_t const rpt_count = hid_info[instance].report_count;
|
||||
tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info;
|
||||
tuh_hid_report_info_t* rpt_info = NULL;
|
||||
|
||||
if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0)
|
||||
{
|
||||
// Simple report without report ID as 1st byte
|
||||
rpt_info = &rpt_info_arr[0];
|
||||
}else
|
||||
{
|
||||
// Composite report, 1st byte is report ID, data starts from 2nd byte
|
||||
uint8_t const rpt_id = report[0];
|
||||
|
||||
// Find report id in the arrray
|
||||
for(uint8_t i=0; i<rpt_count; i++)
|
||||
{
|
||||
if (rpt_id == rpt_info_arr[i].report_id )
|
||||
{
|
||||
rpt_info = &rpt_info_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
report++;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!rpt_info)
|
||||
{
|
||||
printf("Couldn't find the report info for this report !\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
|
||||
// - Keyboard : Desktop, Keyboard
|
||||
// - Mouse : Desktop, Mouse
|
||||
// - Gamepad : Desktop, Gamepad
|
||||
// - Consumer Control (Media Key) : Consumer, Consumer Control
|
||||
// - System Control (Power key) : Desktop, System Control
|
||||
// - Generic (vendor) : 0xFFxx, xx
|
||||
if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP )
|
||||
{
|
||||
switch (rpt_info->usage)
|
||||
{
|
||||
case HID_USAGE_DESKTOP_KEYBOARD:
|
||||
TU_LOG1("HID receive keyboard report\r\n");
|
||||
// Assume keyboard follow boot report layout
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
|
||||
case HID_USAGE_DESKTOP_MOUSE:
|
||||
TU_LOG1("HID receive mouse report\r\n");
|
||||
// Assume mouse follow boot report layout
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
void print_greeting(void);
|
||||
void led_blinking_task(void);
|
||||
|
||||
extern void cdc_task(void);
|
||||
@ -43,7 +42,8 @@ extern void hid_app_task(void);
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
print_greeting();
|
||||
|
||||
printf("TinyUSB Host CDC MSC HID Example\r\n");
|
||||
|
||||
tusb_init();
|
||||
|
||||
@ -126,28 +126,3 @@ void led_blinking_task(void)
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HELPER FUNCTION
|
||||
//--------------------------------------------------------------------+
|
||||
void print_greeting(void)
|
||||
{
|
||||
char const * const rtos_name[] =
|
||||
{
|
||||
[OPT_OS_NONE] = "None",
|
||||
[OPT_OS_FREERTOS] = "FreeRTOS",
|
||||
[OPT_OS_MYNEWT] = "Mynewt OS",
|
||||
[OPT_OS_CUSTOM] = "Custom OS implemnted by application",
|
||||
[OPT_OS_PICO] = "Raspberry Pi Pico SDK",
|
||||
[OPT_OS_RTTHREAD] = "RT-Thread"
|
||||
};
|
||||
|
||||
printf("----------------------------------------------------\r\n");
|
||||
printf("TinyUSB Host Example\r\n");
|
||||
printf("If you find any bugs or problems, feel free to open\r\n");
|
||||
printf("an issue at https://github.com/hathach/tinyusb\r\n");
|
||||
printf("----------------------------------------------------\r\n\r\n");
|
||||
|
||||
printf("This Host demo is configured to support:\r\n");
|
||||
printf(" - RTOS = %s\r\n", rtos_name[CFG_TUSB_OS]);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ void tuh_msc_umount_cb(uint8_t dev_addr)
|
||||
//
|
||||
// if ( phy_disk == f_get_current_drive() )
|
||||
// { // active drive is unplugged --> change to other drive
|
||||
// for(uint8_t i=0; i<CFG_TUSB_HOST_DEVICE_MAX; i++)
|
||||
// for(uint8_t i=0; i<CFG_TUH_DEVICE_MAX; i++)
|
||||
// {
|
||||
// if ( disk_is_ready(i) )
|
||||
// {
|
||||
|
@ -72,19 +72,20 @@
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
#define CFG_TUH_ENUMERATION_BUFSZIE 256
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
#define CFG_TUH_HUB 1
|
||||
#define CFG_TUH_CDC 1
|
||||
#define CFG_TUH_HID 2
|
||||
#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 1
|
||||
#define CFG_TUH_VENDOR 0
|
||||
|
||||
#define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports
|
||||
// max device support (excluding hub device)
|
||||
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
|
||||
|
||||
//------------- HID -------------//
|
||||
|
||||
#define CFG_TUH_HID_EP_BUFSIZE 64
|
||||
#define CFG_TUH_HID_EPIN_BUFSIZE 64
|
||||
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
0
examples/host/hid_controller/.only.MCU_LPC175X_6X
Normal file
0
examples/host/hid_controller/.only.MCU_LPC175X_6X
Normal file
0
examples/host/hid_controller/.only.MCU_LPC177X_8X
Normal file
0
examples/host/hid_controller/.only.MCU_LPC177X_8X
Normal file
0
examples/host/hid_controller/.only.MCU_LPC18XX
Normal file
0
examples/host/hid_controller/.only.MCU_LPC18XX
Normal file
0
examples/host/hid_controller/.only.MCU_LPC40XX
Normal file
0
examples/host/hid_controller/.only.MCU_LPC40XX
Normal file
0
examples/host/hid_controller/.only.MCU_LPC43XX
Normal file
0
examples/host/hid_controller/.only.MCU_LPC43XX
Normal file
0
examples/host/hid_controller/.only.MCU_MIMXRT10XX
Normal file
0
examples/host/hid_controller/.only.MCU_MIMXRT10XX
Normal file
0
examples/host/hid_controller/.only.MCU_RP2040
Normal file
0
examples/host/hid_controller/.only.MCU_RP2040
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user