├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── remove_teensyloader.py ├── .gitignore ├── LICENSE.txt ├── README.md └── teensy └── avr ├── boards.txt └── cores ├── teensy3 ├── WProgram.h ├── usb_desc.c ├── usb_desc.h ├── usb_dev.c ├── usb_dev.h ├── usb_inst.cpp ├── usb_serial.h ├── usb_xinput.c └── usb_xinput.h └── teensy4 ├── WProgram.h ├── usb.c ├── usb_desc.c ├── usb_desc.h ├── usb_inst.cpp ├── usb_serial.h ├── usb_xinput.c └── usb_xinput.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | env: 6 | IDE_VERSION: 1.8.19 7 | TEENSY_VERSION: 159 8 | IDE_LOCATION: /usr/local/share/arduino 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | compilation: ['Serial: Blank Sketch', 'XInput: Blank Sketch', 'USB API Demo', 'XInput Library'] 18 | include: 19 | - compilation: 'Serial: Blank Sketch' 20 | sketch: "$IDE_LOCATION/examples/01.Basics/BareMinimum/BareMinimum.ino" 21 | usb_mode: serial 22 | - compilation: 'XInput: Blank Sketch' 23 | sketch: "$IDE_LOCATION/examples/01.Basics/BareMinimum/BareMinimum.ino" 24 | usb_mode: xinput 25 | - compilation: 'USB API Demo' 26 | sketch: "$IDE_LOCATION/libraries/ArduinoXInput/extras/API-Demo/API-Demo.ino" 27 | usb_mode: xinput 28 | - compilation: 'XInput Library' 29 | sketch: "$IDE_LOCATION/libraries/ArduinoXInput/examples/GamepadPins/GamepadPins.ino" 30 | usb_mode: xinput 31 | 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v4 35 | 36 | - name: Install Arduino IDE 37 | run: | 38 | wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz 39 | tar xf arduino-$IDE_VERSION-linux64.tar.xz 40 | sudo mv arduino-$IDE_VERSION /usr/local/share/arduino 41 | sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino 42 | rm arduino-$IDE_VERSION-linux64.tar.xz 43 | 44 | - name: Install Teensyduino 45 | run: | 46 | wget https://www.pjrc.com/teensy/td_$TEENSY_VERSION/TeensyduinoInstall.linux64; 47 | chmod +x ./TeensyduinoInstall.linux64; 48 | sudo ./TeensyduinoInstall.linux64 --dir=/usr/local/share/arduino; 49 | rm ./TeensyduinoInstall.linux64; 50 | 51 | - name: Install XInput Library 52 | if: contains(matrix.sketch, 'ArduinoXInput') 53 | run: | 54 | git clone https://github.com/dmadison/ArduinoXInput.git; 55 | sudo mv ArduinoXInput $IDE_LOCATION/libraries; 56 | 57 | - name: Copy Teensy XInput Files 58 | run: sudo \cp -r teensy $IDE_LOCATION/hardware; 59 | 60 | - name: Remove Teensy Loader Trigger 61 | run: sudo python ./.github/workflows/remove_teensyloader.py $IDE_LOCATION/hardware/teensy/avr/platform.txt 62 | 63 | - name: Teensy LC 64 | run: arduino --verify --board teensy:avr:teensyLC:usb=${{ matrix.usb_mode }},speed=48,opt=o2std,keys=en-us ${{ matrix.sketch }}; 65 | 66 | - name: Teensy 3.1/ 3.2 67 | run: arduino --verify --board teensy:avr:teensy31:usb=${{ matrix.usb_mode }},speed=72,opt=o2std,keys=en-us ${{ matrix.sketch }}; 68 | 69 | - name: Teensy 3.5 70 | run: arduino --verify --board teensy:avr:teensy35:usb=${{ matrix.usb_mode }},speed=120,opt=o2std,keys=en-us ${{ matrix.sketch }}; 71 | 72 | - name: Teensy 3.6 73 | run: arduino --verify --board teensy:avr:teensy36:usb=${{ matrix.usb_mode }},speed=180,opt=o2std,keys=en-us ${{ matrix.sketch }}; 74 | 75 | - name: Teensy 4.0 76 | run: arduino --verify --board teensy:avr:teensy40:usb=${{ matrix.usb_mode }},speed=600,opt=o2std,keys=en-us ${{ matrix.sketch }}; 77 | 78 | - name: Teensy 4.1 79 | run: arduino --verify --board teensy:avr:teensy41:usb=${{ matrix.usb_mode }},speed=600,opt=o2std,keys=en-us ${{ matrix.sketch }}; 80 | 81 | - name: Teensy MicroMod 82 | run: arduino --verify --board teensy:avr:teensyMM:usb=${{ matrix.usb_mode }},speed=600,opt=o2std,keys=en-us ${{ matrix.sketch }}; 83 | -------------------------------------------------------------------------------- /.github/workflows/remove_teensyloader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import re 5 | 6 | filepath = sys.argv[1] # path of the file to parse 7 | lines = [] # list of lines from the file 8 | removed = False # flag for if the line was removed from the file 9 | 10 | with open(filepath, 'r') as f: 11 | lines = f.readlines() 12 | 13 | with open(filepath, 'w') as f: 14 | # matching "postbuild" hooks of any number which call the "teensy_post_compile" application 15 | pattern = re.compile("recipe\.hooks\.postbuild\.[0-9]\.pattern=\"{teensytools\.path}teensy_post_compile\"") 16 | for line in lines: 17 | if not pattern.match(line): 18 | f.write(line) 19 | else: 20 | print("Removing line '{}'".format(line.strip('\n'))) 21 | removed = True 22 | 23 | if not removed: 24 | raise RuntimeError("Did not find a matching line to remove in \"{}\"".format(filepath)) 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # wip stuff 31 | wip.* 32 | 33 | # ========================= 34 | # Operating System Files 35 | # ========================= 36 | 37 | # OSX 38 | # ========================= 39 | 40 | .DS_Store 41 | .AppleDouble 42 | .LSOverride 43 | 44 | # Thumbnails 45 | ._* 46 | 47 | # Files that might appear on external disk 48 | .Spotlight-V100 49 | .Trashes 50 | 51 | # Directories potentially created on remote AFP share 52 | .AppleDB 53 | .AppleDesktop 54 | Network Trash Folder 55 | Temporary Items 56 | .apdisk 57 | 58 | # Windows 59 | # ========================= 60 | 61 | # Windows image file caches 62 | Thumbs.db 63 | ehthumbs.db 64 | 65 | # Folder config file 66 | Desktop.ini 67 | 68 | # Recycle Bin used on file shares 69 | $RECYCLE.BIN/ 70 | 71 | # Windows Installer files 72 | *.cab 73 | *.msi 74 | *.msm 75 | *.msp 76 | 77 | # Windows shortcuts 78 | *.lnk 79 | *.zip 80 | 81 | ## ---------------------------------------------------- 82 | ## Arduino XInput - Teensy Boards Files 83 | 84 | # boards.txt 85 | teensy/** 86 | !teensy/avr/ 87 | !teensy/avr/boards.txt 88 | 89 | # cores files 90 | !teensy/avr/cores/ 91 | !teensy/avr/cores/teensy3/ 92 | !teensy/avr/cores/teensy3/usb_desc.c 93 | !teensy/avr/cores/teensy3/usb_desc.h 94 | !teensy/avr/cores/teensy3/usb_dev.h 95 | !teensy/avr/cores/teensy3/usb_dev.c 96 | !teensy/avr/cores/teensy3/usb_xinput.c 97 | !teensy/avr/cores/teensy3/usb_xinput.h 98 | !teensy/avr/cores/teensy3/usb_inst.cpp 99 | !teensy/avr/cores/teensy3/usb_serial.h 100 | !teensy/avr/cores/teensy3/WProgram.h 101 | 102 | !teensy/avr/cores/teensy4/ 103 | !teensy/avr/cores/teensy4/WProgram.h 104 | !teensy/avr/cores/teensy4/usb.c 105 | !teensy/avr/cores/teensy4/usb_desc.c 106 | !teensy/avr/cores/teensy4/usb_desc.h 107 | !teensy/avr/cores/teensy4/usb_inst.cpp 108 | !teensy/avr/cores/teensy4/usb_serial.h 109 | !teensy/avr/cores/teensy4/usb_xinput.h 110 | !teensy/avr/cores/teensy4/usb_xinput.c 111 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Teensyduino Core Library 2 | http://www.pjrc.com/teensy/ 3 | Copyright (c) 2017 PJRC.COM, LLC. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | 1. The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | 2. If the Software is incorporated into a build system that allows 17 | selection among a list of target devices, then similar target 18 | devices manufactured by PJRC.COM must be included in the list of 19 | target devices and selectable in the same manner. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | 30 | ############################################################################## 31 | 32 | Teensy XInput USB Mode 33 | MIT License 34 | 35 | Copyright (c) 2017 Zachery Littell 36 | Copyright (c) 2019 David Madison 37 | 38 | Permission is hereby granted, free of charge, to any person obtaining a copy 39 | of this software and associated documentation files (the "Software"), to deal 40 | in the Software without restriction, including without limitation the rights 41 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 42 | copies of the Software, and to permit persons to whom the Software is 43 | furnished to do so, subject to the following conditions: 44 | 45 | The above copyright notice and this permission notice shall be included in all 46 | copies or substantial portions of the Software. 47 | 48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 51 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 52 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 | SOFTWARE. 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Teensy XInput USB Mode 2 | [![Build Status](https://github.com/dmadison/ArduinoXInput_Teensy/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/dmadison/ArduinoXInput_Teensy/actions?query=workflow%3Abuild) 3 | 4 | The files in this repository will add an additional USB mode ("XInput") to your Teensy board, allowing it to emulate an Xbox gamepad. 5 | 6 | This is meant to be used in conjunction with the [ArduinoXInput library](https://github.com/dmadison/ArduinoXInput). 7 | 8 | ## Installation 9 | 10 | You must have both [the Arduino IDE](https://www.arduino.cc/en/main/software) and [Teensyduino](https://www.pjrc.com/teensy/td_download.html) installed before proceeding. 11 | 12 | Double-check that your installed Teensyduino version matches the files provided in this repository. This repository is currently using [**Teensyduino 1.59**](https://www.pjrc.com/teensy/td_159). You can download older versions on [the releases page](../../releases). 13 | 14 | If you don't know your Teensyduino version, compile a blank sketch with a Teensy board selected and the Teensy Loader will open. In the Teensy Loader window select `Help -> About` and it will tell you the version number. If your version does not match you will have to reinstall or update the Teensyduino software. 15 | 16 | It is recommended that you make a backup of your hardware folder before proceeding in case something goes wrong or if you want to revert the installation. 17 | 18 | To install the XInput modifications, copy the files from the repository's "teensy" directory into the hardware folder and replace any pre-existing files. This will not affect your saved sketches. 19 | 20 | To remove the XInput modifications, restore your Teensy hardware folder from backup or reinstall the Teensyduino software. 21 | 22 | #### Arduino IDE 1.x 23 | 24 | For IDE version 1.x the Teensy hardware files are located in your Arduino IDE installation directory. 25 | 26 | On Windows this is typically in your "Program Files" folder: 27 | ``` 28 | C:\Program Files (x86)\Arduino\hardware\teensy\avr 29 | ``` 30 | 31 | On macOS this is the folder path: 32 | ``` 33 | ~/Library/Arduino/hardware/teensy/avr 34 | ``` 35 | 36 | #### Arduino IDE 2.x 37 | 38 | For IDE version 2.x the Teensy hardware files are located in your application data folder. 39 | 40 | On Windows this is typically at the following path: 41 | ``` 42 | %AppData%\..\Local\Arduino15\packages\teensy\hardware\avr\{version} 43 | ``` 44 | 45 | On macOS this is the folder path: 46 | ``` 47 | ~/Library/Arduino15/packages/teensy/hardware/avr/{version} 48 | ``` 49 | 50 | Where `{version}` is the installed version number of the Teensyduino software. 51 | 52 | Version 2 of the IDE is reported to have issues with caching board files, which may prevent this project from loading or functioning properly. Consider using the version 1 IDE if you run into problems with installation. 53 | 54 | ## Supported Boards 55 | 56 | * [Teensy 3.6](https://www.pjrc.com/store/teensy36.html) 57 | * [Teensy 3.5](https://www.pjrc.com/store/teensy35.html) 58 | * [Teensy 3.1](https://www.pjrc.com/store/teensy31.html) / [3.2](https://www.pjrc.com/store/teensy32.html) 59 | * [Teensy LC](https://www.pjrc.com/store/teensylc.html) 60 | * [Teensy 4.0](https://www.pjrc.com/store/teensy40.html) 61 | * [Teensy 4.1](https://www.pjrc.com/store/teensy41.html) 62 | * [Teensy MicroMod](https://www.sparkfun.com/products/16402) 63 | 64 | ## Limitations 65 | 66 | ### No Console Support 67 | 68 | This will *not* enable you to use your Teensy with an Xbox console! Genuine controllers use a dedicated hardware security chip that handshakes with the console. The Teensy boards do not have this chip, and its security method has not been (openly) broken. 69 | 70 | ### No Commercial Use 71 | 72 | These board definitions make use of Microsoft's VID and PID in order to latch on to the PC driver. As such this is strictly for educational or development use by non-commercial entities. 73 | 74 | ## Credits and Contributions 75 | 76 | A massive thank you to Zach Littell, whose did all of the original legwork in putting this together. Check out some of his stuff at [zlittell.com](http://www.zlittell.com). 77 | 78 | Another big thanks for Tom Mason ([@wheybags](https://github.com/wheybags)), who added support for the Teensy 4 boards ([#26](https://github.com/dmadison/ArduinoXInput_Teensy/pull/26)). 79 | 80 | ## License 81 | 82 | The original Teensy core files and their modified versions are licensed under a modified version of the permissive [MIT license](https://opensource.org/licenses/MIT). Newly contributed files are licensed under the MIT license with no additional stipulations. 83 | 84 | See the [LICENSE](LICENSE.txt) file for more information. 85 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/WProgram.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #ifndef WProgram_h 32 | #define WProgram_h 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | // some libraries and sketches depend on this 40 | // AVR stuff, assuming Arduino.h or WProgram.h 41 | // automatically includes it... 42 | #include 43 | #include 44 | 45 | #include "avr_functions.h" 46 | #include "wiring.h" 47 | #include "HardwareSerial.h" 48 | 49 | #define DMAMEM __attribute__ ((section(".dmabuffers"), used)) 50 | #define FASTRUN __attribute__ ((section(".fastrun"), noinline, noclone )) 51 | 52 | #ifdef __cplusplus 53 | 54 | #include "inplace_function.h" 55 | #include "avr_emulation.h" 56 | #include "usb_serial.h" 57 | #include "usb_serial2.h" 58 | #include "usb_serial3.h" 59 | #include "usb_seremu.h" 60 | #include "usb_keyboard.h" 61 | #include "usb_mouse.h" 62 | #include "usb_joystick.h" 63 | #include "usb_midi.h" 64 | #include "usb_rawhid.h" 65 | #include "usb_flightsim.h" 66 | #include "usb_mtp.h" 67 | #include "usb_audio.h" 68 | #include "usb_touch.h" 69 | 70 | #include "usb_xinput.h" 71 | 72 | #include "usb_undef.h" // do not allow usb_desc.h stuff to leak to user programs 73 | 74 | #include "WCharacter.h" 75 | #include "WString.h" 76 | #include "elapsedMillis.h" 77 | #include "IntervalTimer.h" 78 | #include "CrashReport.h" 79 | 80 | uint16_t makeWord(uint16_t w); 81 | uint16_t makeWord(byte h, byte l); 82 | 83 | #define word(...) makeWord(__VA_ARGS__) 84 | 85 | unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); 86 | 87 | void tone(uint8_t pin, uint16_t frequency, uint32_t duration = 0); 88 | void noTone(uint8_t pin); 89 | 90 | // WMath prototypes 91 | int32_t random(void); 92 | uint32_t random(uint32_t howbig); 93 | int32_t random(int32_t howsmall, int32_t howbig); 94 | void randomSeed(uint32_t newseed); 95 | void srandom(unsigned int newseed); 96 | 97 | #include "pins_arduino.h" 98 | 99 | #endif // __cplusplus 100 | 101 | 102 | // Fast memcpy 103 | #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) 104 | #ifdef __cplusplus 105 | extern "C" { 106 | extern void *memcpy (void *dst, const void *src, size_t count); 107 | } 108 | #else 109 | extern void *memcpy (void *dst, const void *src, size_t count); 110 | #endif 111 | #endif 112 | 113 | 114 | #endif // WProgram_h 115 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_desc.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #ifndef _usb_desc_h_ 32 | #define _usb_desc_h_ 33 | 34 | // This header is NOT meant to be included when compiling 35 | // user sketches in Arduino. The low-level functions 36 | // provided by usb_dev.c are meant to be called only by 37 | // code which provides higher-level interfaces to the user. 38 | 39 | #include 40 | #include 41 | 42 | #define ENDPOINT_UNUSED 0x00 43 | #define ENDPOINT_TRANSMIT_ONLY 0x15 44 | #define ENDPOINT_RECEIVE_ONLY 0x19 45 | #define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D 46 | #define ENDPOINT_RECEIVE_ISOCHRONOUS 0x18 47 | #define ENDPOINT_TRANSMIT_ISOCHRONOUS 0x14 48 | 49 | /* 50 | Each group of #define lines below corresponds to one of the 51 | settings in the Tools > USB Type menu. This file defines what 52 | type of USB device is actually created for each of those menu 53 | options. 54 | 55 | Each "interface" is a set of functionality your PC or Mac will 56 | use and treat as if it is a unique device. Within each interface, 57 | the "endpoints" are the actual communication channels. Most 58 | interfaces use 1, 2 or 3 endpoints. By editing only this file, 59 | you can customize the USB Types to be any collection of interfaces. 60 | 61 | To modify a USB Type, delete the XYZ_INTERFACE lines for any 62 | interfaces you wish to remove, and copy them from another USB Type 63 | for any you want to add. 64 | 65 | Give each interface a unique number, and edit NUM_INTERFACE to 66 | reflect the total number of interfaces. 67 | 68 | Next, assign unique endpoint numbers to all the endpoints across 69 | all the interfaces your device has. You can reuse an endpoint 70 | number for transmit and receive, but the same endpoint number must 71 | not be used twice to transmit, or twice to receive. 72 | 73 | Most endpoints also require their maximum size, and some also 74 | need an interval specification (the number of milliseconds the 75 | PC will check for data from that endpoint). For existing 76 | interfaces, usually these other settings should not be changed. 77 | 78 | Edit NUM_ENDPOINTS to be at least the largest endpoint number used. 79 | 80 | Edit NUM_USB_BUFFERS to control how much memory the USB stack will 81 | allocate. At least 2 should be used for each endpoint. More 82 | memory will allow higher throughput for user programs that have 83 | high latency (eg, spending time doing things other than interacting 84 | with the USB). 85 | 86 | Edit the ENDPOINT*_CONFIG lines so each endpoint is configured 87 | the proper way (transmit, receive, or both). 88 | 89 | If you are using existing interfaces (making your own device with 90 | a different set of interfaces) the code in all other files should 91 | automatically adapt to the new endpoints you specify here. 92 | 93 | If you need to create a new type of interface, you'll need to write 94 | the code which sends and receives packets, and presents an API to 95 | the user. Usually, a pair of files are added for the actual code, 96 | and code is also added in usb_dev.c for any control transfers, 97 | interrupt-level code, or other very low-level stuff not possible 98 | from the packet send/receive functons. Code also is added in 99 | usb_inst.c to create an instance of your C++ object. This message 100 | gives a quick summary of things you will need to know: 101 | https://forum.pjrc.com/threads/49045?p=164512&viewfull=1#post164512 102 | 103 | You may edit the Vendor and Product ID numbers, and strings. If 104 | the numbers are changed, Teensyduino may not be able to automatically 105 | find and reboot your board when you click the Upload button in 106 | the Arduino IDE. You will need to press the Program button on 107 | Teensy to initiate programming. 108 | 109 | Some operating systems, especially Windows, may cache USB device 110 | info. Changes to the device name may not update on the same 111 | computer unless the vendor or product ID numbers change, or the 112 | "bcdDevice" revision code is increased. 113 | 114 | If these instructions are missing steps or could be improved, please 115 | let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports 116 | */ 117 | 118 | 119 | #if defined(USB_SERIAL) 120 | #define VENDOR_ID 0x16C0 121 | #define PRODUCT_ID 0x0483 122 | #define DEVICE_CLASS 2 // 2 = Communication Class 123 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 124 | #define MANUFACTURER_NAME_LEN 11 125 | #define PRODUCT_NAME {'U','S','B',' ','S','e','r','i','a','l'} 126 | #define PRODUCT_NAME_LEN 10 127 | #define EP0_SIZE 64 128 | #define NUM_ENDPOINTS 4 129 | #define NUM_USB_BUFFERS 12 130 | #define NUM_INTERFACE 2 131 | #define CDC_STATUS_INTERFACE 0 132 | #define CDC_DATA_INTERFACE 1 133 | #define CDC_ACM_ENDPOINT 2 134 | #define CDC_RX_ENDPOINT 3 135 | #define CDC_TX_ENDPOINT 4 136 | #define CDC_ACM_SIZE 16 137 | #define CDC_RX_SIZE 64 138 | #define CDC_TX_SIZE 64 139 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY 140 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 141 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 142 | 143 | #elif defined(USB_DUAL_SERIAL) 144 | #define VENDOR_ID 0x16C0 145 | #define PRODUCT_ID 0x048B 146 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 147 | #define MANUFACTURER_NAME_LEN 11 148 | #define PRODUCT_NAME {'D','u','a','l',' ','S','e','r','i','a','l'} 149 | #define PRODUCT_NAME_LEN 11 150 | #define EP0_SIZE 64 151 | #define NUM_ENDPOINTS 7 152 | #define NUM_USB_BUFFERS 22 153 | #define NUM_INTERFACE 4 154 | #define CDC_IAD_DESCRIPTOR 1 // Serial 155 | #define CDC_STATUS_INTERFACE 0 156 | #define CDC_DATA_INTERFACE 1 157 | #define CDC_ACM_ENDPOINT 2 158 | #define CDC_RX_ENDPOINT 3 159 | #define CDC_TX_ENDPOINT 4 160 | #define CDC_ACM_SIZE 16 161 | #define CDC_RX_SIZE 64 162 | #define CDC_TX_SIZE 64 163 | #define CDC2_STATUS_INTERFACE 2 // SerialUSB1 164 | #define CDC2_DATA_INTERFACE 3 165 | #define CDC2_ACM_ENDPOINT 5 166 | #define CDC2_RX_ENDPOINT 6 167 | #define CDC2_TX_ENDPOINT 7 168 | #define CDC2_ACM_SIZE 16 169 | #define CDC2_RX_SIZE 64 170 | #define CDC2_TX_SIZE 64 171 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY 172 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 173 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 174 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 175 | #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY 176 | #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY 177 | 178 | #elif defined(USB_TRIPLE_SERIAL) 179 | #define VENDOR_ID 0x16C0 180 | #define PRODUCT_ID 0x048C 181 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 182 | #define MANUFACTURER_NAME_LEN 11 183 | #define PRODUCT_NAME {'T','r','i','p','l','e',' ','S','e','r','i','a','l'} 184 | #define PRODUCT_NAME_LEN 13 185 | #define EP0_SIZE 64 186 | #define NUM_ENDPOINTS 10 187 | #define NUM_USB_BUFFERS 32 188 | #define NUM_INTERFACE 6 189 | #define CDC_IAD_DESCRIPTOR 1 // Serial 190 | #define CDC_STATUS_INTERFACE 0 191 | #define CDC_DATA_INTERFACE 1 192 | #define CDC_ACM_ENDPOINT 2 193 | #define CDC_RX_ENDPOINT 3 194 | #define CDC_TX_ENDPOINT 4 195 | #define CDC_ACM_SIZE 16 196 | #define CDC_RX_SIZE 64 197 | #define CDC_TX_SIZE 64 198 | #define CDC2_STATUS_INTERFACE 2 // SerialUSB1 199 | #define CDC2_DATA_INTERFACE 3 200 | #define CDC2_ACM_ENDPOINT 5 201 | #define CDC2_RX_ENDPOINT 6 202 | #define CDC2_TX_ENDPOINT 7 203 | #define CDC2_ACM_SIZE 16 204 | #define CDC2_RX_SIZE 64 205 | #define CDC2_TX_SIZE 64 206 | #define CDC3_STATUS_INTERFACE 4 // SerialUSB2 207 | #define CDC3_DATA_INTERFACE 5 208 | #define CDC3_ACM_ENDPOINT 8 209 | #define CDC3_RX_ENDPOINT 9 210 | #define CDC3_TX_ENDPOINT 10 211 | #define CDC3_ACM_SIZE 16 212 | #define CDC3_RX_SIZE 64 213 | #define CDC3_TX_SIZE 64 214 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY 215 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 216 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 217 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 218 | #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY 219 | #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY 220 | #define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY 221 | #define ENDPOINT9_CONFIG ENDPOINT_RECEIVE_ONLY 222 | #define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY 223 | 224 | #elif defined(USB_KEYBOARDONLY) 225 | #define VENDOR_ID 0x16C0 226 | #define PRODUCT_ID 0x04D0 227 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 228 | #define MANUFACTURER_NAME_LEN 11 229 | #define PRODUCT_NAME {'K','e','y','b','o','a','r','d'} 230 | #define PRODUCT_NAME_LEN 8 231 | #define EP0_SIZE 64 232 | #define NUM_ENDPOINTS 4 233 | #define NUM_USB_BUFFERS 14 234 | #define NUM_INTERFACE 3 235 | #define SEREMU_INTERFACE 1 // Serial emulation 236 | #define SEREMU_TX_ENDPOINT 1 237 | #define SEREMU_TX_SIZE 64 238 | #define SEREMU_TX_INTERVAL 1 239 | #define SEREMU_RX_ENDPOINT 2 240 | #define SEREMU_RX_SIZE 32 241 | #define SEREMU_RX_INTERVAL 2 242 | #define KEYBOARD_INTERFACE 0 // Keyboard 243 | #define KEYBOARD_ENDPOINT 3 244 | #define KEYBOARD_SIZE 8 245 | #define KEYBOARD_INTERVAL 1 246 | #define KEYMEDIA_INTERFACE 2 // Keyboard Media Keys 247 | #define KEYMEDIA_ENDPOINT 4 248 | #define KEYMEDIA_SIZE 8 249 | #define KEYMEDIA_INTERVAL 4 250 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 251 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 252 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 253 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 254 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 255 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 256 | 257 | #elif defined(USB_HID) 258 | #define VENDOR_ID 0x16C0 259 | #define PRODUCT_ID 0x0482 260 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 261 | #define MANUFACTURER_NAME_LEN 11 262 | #define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} 263 | #define PRODUCT_NAME_LEN 23 264 | #define EP0_SIZE 64 265 | #define NUM_ENDPOINTS 6 266 | #define NUM_USB_BUFFERS 24 267 | #define NUM_INTERFACE 5 268 | #define SEREMU_INTERFACE 2 // Serial emulation 269 | #define SEREMU_TX_ENDPOINT 1 270 | #define SEREMU_TX_SIZE 64 271 | #define SEREMU_TX_INTERVAL 1 272 | #define SEREMU_RX_ENDPOINT 2 273 | #define SEREMU_RX_SIZE 32 274 | #define SEREMU_RX_INTERVAL 2 275 | #define KEYBOARD_INTERFACE 0 // Keyboard 276 | #define KEYBOARD_ENDPOINT 3 277 | #define KEYBOARD_SIZE 8 278 | #define KEYBOARD_INTERVAL 1 279 | #define KEYMEDIA_INTERFACE 4 // Keyboard Media Keys 280 | #define KEYMEDIA_ENDPOINT 6 281 | #define KEYMEDIA_SIZE 8 282 | #define KEYMEDIA_INTERVAL 4 283 | #define MOUSE_INTERFACE 1 // Mouse 284 | #define MOUSE_ENDPOINT 5 285 | #define MOUSE_SIZE 8 286 | #define MOUSE_INTERVAL 1 287 | #define JOYSTICK_INTERFACE 3 // Joystick 288 | #define JOYSTICK_ENDPOINT 4 289 | #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick 290 | #define JOYSTICK_INTERVAL 2 291 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 292 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 293 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 294 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 295 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 296 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 297 | 298 | #elif defined(USB_SERIAL_HID) 299 | #define VENDOR_ID 0x16C0 300 | #define PRODUCT_ID 0x0487 301 | #define DEVICE_CLASS 0xEF 302 | #define DEVICE_SUBCLASS 0x02 303 | #define DEVICE_PROTOCOL 0x01 304 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 305 | #define MANUFACTURER_NAME_LEN 11 306 | #define PRODUCT_NAME {'S','e','r','i','a','l','/','K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} 307 | #define PRODUCT_NAME_LEN 30 308 | #define EP0_SIZE 64 309 | #define NUM_ENDPOINTS 7 310 | #define NUM_USB_BUFFERS 30 311 | #define NUM_INTERFACE 6 312 | #define CDC_IAD_DESCRIPTOR 1 313 | #define CDC_STATUS_INTERFACE 0 314 | #define CDC_DATA_INTERFACE 1 // Serial 315 | #define CDC_ACM_ENDPOINT 2 316 | #define CDC_RX_ENDPOINT 3 317 | #define CDC_TX_ENDPOINT 4 318 | #define CDC_ACM_SIZE 16 319 | #define CDC_RX_SIZE 64 320 | #define CDC_TX_SIZE 64 321 | #define KEYBOARD_INTERFACE 2 // Keyboard 322 | #define KEYBOARD_ENDPOINT 1 323 | #define KEYBOARD_SIZE 8 324 | #define KEYBOARD_INTERVAL 1 325 | #define KEYMEDIA_INTERFACE 5 // Keyboard Media Keys 326 | #define KEYMEDIA_ENDPOINT 7 327 | #define KEYMEDIA_SIZE 8 328 | #define KEYMEDIA_INTERVAL 4 329 | #define MOUSE_INTERFACE 3 // Mouse 330 | #define MOUSE_ENDPOINT 5 331 | #define MOUSE_SIZE 8 332 | #define MOUSE_INTERVAL 2 333 | #define JOYSTICK_INTERFACE 4 // Joystick 334 | #define JOYSTICK_ENDPOINT 6 335 | #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick 336 | #define JOYSTICK_INTERVAL 1 337 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 338 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY 339 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 340 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 341 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 342 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 343 | #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY 344 | 345 | #elif defined(USB_TOUCHSCREEN) 346 | #define VENDOR_ID 0x16C0 347 | #define PRODUCT_ID 0x04D3 348 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 349 | #define MANUFACTURER_NAME_LEN 11 350 | #define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','T','o','u','c','h','s','c','r','e','e','n'} 351 | #define PRODUCT_NAME_LEN 20 352 | #define EP0_SIZE 64 353 | #define NUM_ENDPOINTS 5 354 | #define NUM_USB_BUFFERS 15 355 | #define NUM_INTERFACE 4 356 | #define SEREMU_INTERFACE 1 // Serial emulation 357 | #define SEREMU_TX_ENDPOINT 1 358 | #define SEREMU_TX_SIZE 64 359 | #define SEREMU_TX_INTERVAL 1 360 | #define SEREMU_RX_ENDPOINT 2 361 | #define SEREMU_RX_SIZE 32 362 | #define SEREMU_RX_INTERVAL 2 363 | #define KEYBOARD_INTERFACE 0 // Keyboard 364 | #define KEYBOARD_ENDPOINT 3 365 | #define KEYBOARD_SIZE 8 366 | #define KEYBOARD_INTERVAL 1 367 | #define KEYMEDIA_INTERFACE 2 // Keyboard Media Keys 368 | #define KEYMEDIA_ENDPOINT 4 369 | #define KEYMEDIA_SIZE 8 370 | #define KEYMEDIA_INTERVAL 4 371 | #define MULTITOUCH_INTERFACE 3 // Touchscreen 372 | #define MULTITOUCH_ENDPOINT 5 373 | #define MULTITOUCH_SIZE 16 374 | #define MULTITOUCH_FINGERS 10 375 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 376 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 377 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 378 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 379 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 380 | 381 | #elif defined(USB_HID_TOUCHSCREEN) 382 | #define VENDOR_ID 0x16C0 383 | #define PRODUCT_ID 0x04D4 384 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 385 | #define MANUFACTURER_NAME_LEN 11 386 | #define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','T','o','u','c','h','s','c','r','e','e','n'} 387 | #define PRODUCT_NAME_LEN 26 388 | #define EP0_SIZE 64 389 | #define NUM_ENDPOINTS 6 390 | #define NUM_USB_BUFFERS 20 391 | #define NUM_INTERFACE 5 392 | #define SEREMU_INTERFACE 2 // Serial emulation 393 | #define SEREMU_TX_ENDPOINT 1 394 | #define SEREMU_TX_SIZE 64 395 | #define SEREMU_TX_INTERVAL 1 396 | #define SEREMU_RX_ENDPOINT 2 397 | #define SEREMU_RX_SIZE 32 398 | #define SEREMU_RX_INTERVAL 2 399 | #define KEYBOARD_INTERFACE 0 // Keyboard 400 | #define KEYBOARD_ENDPOINT 3 401 | #define KEYBOARD_SIZE 8 402 | #define KEYBOARD_INTERVAL 1 403 | #define KEYMEDIA_INTERFACE 3 // Keyboard Media Keys 404 | #define KEYMEDIA_ENDPOINT 4 405 | #define KEYMEDIA_SIZE 8 406 | #define KEYMEDIA_INTERVAL 4 407 | #define MOUSE_INTERFACE 1 // Mouse 408 | #define MOUSE_ENDPOINT 6 409 | #define MOUSE_SIZE 8 410 | #define MOUSE_INTERVAL 2 411 | #define MULTITOUCH_INTERFACE 4 // Touchscreen 412 | #define MULTITOUCH_ENDPOINT 5 413 | #define MULTITOUCH_SIZE 16 414 | #define MULTITOUCH_FINGERS 10 415 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 416 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 417 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 418 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 419 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 420 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 421 | 422 | #elif defined(USB_MIDI) 423 | #define VENDOR_ID 0x16C0 424 | #define PRODUCT_ID 0x0485 425 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 426 | #define MANUFACTURER_NAME_LEN 11 427 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I'} 428 | #define PRODUCT_NAME_LEN 11 429 | #define EP0_SIZE 64 430 | #define NUM_ENDPOINTS 4 431 | #define NUM_USB_BUFFERS 16 432 | #define NUM_INTERFACE 2 433 | #define SEREMU_INTERFACE 1 // Serial emulation 434 | #define SEREMU_TX_ENDPOINT 1 435 | #define SEREMU_TX_SIZE 64 436 | #define SEREMU_TX_INTERVAL 1 437 | #define SEREMU_RX_ENDPOINT 2 438 | #define SEREMU_RX_SIZE 32 439 | #define SEREMU_RX_INTERVAL 2 440 | #define MIDI_INTERFACE 0 // MIDI 441 | #define MIDI_NUM_CABLES 1 442 | #define MIDI_TX_ENDPOINT 3 443 | #define MIDI_TX_SIZE 64 444 | #define MIDI_RX_ENDPOINT 4 445 | #define MIDI_RX_SIZE 64 446 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 447 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 448 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 449 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 450 | 451 | #elif defined(USB_MIDI4) 452 | #define VENDOR_ID 0x16C0 453 | #define PRODUCT_ID 0x0485 454 | #define BCD_DEVICE 0x0211 455 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 456 | #define MANUFACTURER_NAME_LEN 11 457 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','4'} 458 | #define PRODUCT_NAME_LEN 13 459 | #define EP0_SIZE 64 460 | #define NUM_ENDPOINTS 4 461 | #define NUM_USB_BUFFERS 16 462 | #define NUM_INTERFACE 2 463 | #define SEREMU_INTERFACE 1 // Serial emulation 464 | #define SEREMU_TX_ENDPOINT 1 465 | #define SEREMU_TX_SIZE 64 466 | #define SEREMU_TX_INTERVAL 1 467 | #define SEREMU_RX_ENDPOINT 2 468 | #define SEREMU_RX_SIZE 32 469 | #define SEREMU_RX_INTERVAL 2 470 | #define MIDI_INTERFACE 0 // MIDI 471 | #define MIDI_NUM_CABLES 4 472 | #define MIDI_TX_ENDPOINT 3 473 | #define MIDI_TX_SIZE 64 474 | #define MIDI_RX_ENDPOINT 4 475 | #define MIDI_RX_SIZE 64 476 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 477 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 478 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 479 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 480 | 481 | #elif defined(USB_MIDI16) 482 | #define VENDOR_ID 0x16C0 483 | #define PRODUCT_ID 0x0485 484 | #define BCD_DEVICE 0x0212 485 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 486 | #define MANUFACTURER_NAME_LEN 11 487 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','1','6'} 488 | #define PRODUCT_NAME_LEN 14 489 | #define EP0_SIZE 64 490 | #define NUM_ENDPOINTS 4 491 | #define NUM_USB_BUFFERS 16 492 | #define NUM_INTERFACE 2 493 | #define SEREMU_INTERFACE 1 // Serial emulation 494 | #define SEREMU_TX_ENDPOINT 1 495 | #define SEREMU_TX_SIZE 64 496 | #define SEREMU_TX_INTERVAL 1 497 | #define SEREMU_RX_ENDPOINT 2 498 | #define SEREMU_RX_SIZE 32 499 | #define SEREMU_RX_INTERVAL 2 500 | #define MIDI_INTERFACE 0 // MIDI 501 | #define MIDI_NUM_CABLES 16 502 | #define MIDI_TX_ENDPOINT 3 503 | #define MIDI_TX_SIZE 64 504 | #define MIDI_RX_ENDPOINT 4 505 | #define MIDI_RX_SIZE 64 506 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 507 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 508 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 509 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 510 | 511 | #elif defined(USB_MIDI_SERIAL) 512 | #define VENDOR_ID 0x16C0 513 | #define PRODUCT_ID 0x0489 514 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 515 | #define MANUFACTURER_NAME_LEN 11 516 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I'} 517 | #define PRODUCT_NAME_LEN 11 518 | #define EP0_SIZE 64 519 | #define NUM_ENDPOINTS 5 520 | #define NUM_USB_BUFFERS 30 521 | #define NUM_INTERFACE 3 522 | #define CDC_IAD_DESCRIPTOR 1 523 | #define CDC_STATUS_INTERFACE 0 524 | #define CDC_DATA_INTERFACE 1 // Serial 525 | #define CDC_ACM_ENDPOINT 1 526 | #define CDC_RX_ENDPOINT 2 527 | #define CDC_TX_ENDPOINT 3 528 | #define CDC_ACM_SIZE 16 529 | #define CDC_RX_SIZE 64 530 | #define CDC_TX_SIZE 64 531 | #define MIDI_INTERFACE 2 // MIDI 532 | #define MIDI_NUM_CABLES 1 533 | #define MIDI_TX_ENDPOINT 4 534 | #define MIDI_TX_SIZE 64 535 | #define MIDI_RX_ENDPOINT 5 536 | #define MIDI_RX_SIZE 64 537 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 538 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 539 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 540 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 541 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 542 | 543 | #elif defined(USB_MIDI4_SERIAL) 544 | #define VENDOR_ID 0x16C0 545 | #define PRODUCT_ID 0x0489 546 | #define BCD_DEVICE 0x0211 547 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 548 | #define MANUFACTURER_NAME_LEN 11 549 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','4'} 550 | #define PRODUCT_NAME_LEN 13 551 | #define EP0_SIZE 64 552 | #define NUM_ENDPOINTS 5 553 | #define NUM_USB_BUFFERS 30 554 | #define NUM_INTERFACE 3 555 | #define CDC_IAD_DESCRIPTOR 1 556 | #define CDC_STATUS_INTERFACE 0 557 | #define CDC_DATA_INTERFACE 1 // Serial 558 | #define CDC_ACM_ENDPOINT 1 559 | #define CDC_RX_ENDPOINT 2 560 | #define CDC_TX_ENDPOINT 3 561 | #define CDC_ACM_SIZE 16 562 | #define CDC_RX_SIZE 64 563 | #define CDC_TX_SIZE 64 564 | #define MIDI_INTERFACE 2 // MIDI 565 | #define MIDI_NUM_CABLES 4 566 | #define MIDI_TX_ENDPOINT 4 567 | #define MIDI_TX_SIZE 64 568 | #define MIDI_RX_ENDPOINT 5 569 | #define MIDI_RX_SIZE 64 570 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 571 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 572 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 573 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 574 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 575 | 576 | #elif defined(USB_MIDI16_SERIAL) 577 | #define VENDOR_ID 0x16C0 578 | #define PRODUCT_ID 0x0489 579 | #define BCD_DEVICE 0x0212 580 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 581 | #define MANUFACTURER_NAME_LEN 11 582 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','1','6'} 583 | #define PRODUCT_NAME_LEN 14 584 | #define EP0_SIZE 64 585 | #define NUM_ENDPOINTS 5 586 | #define NUM_USB_BUFFERS 30 587 | #define NUM_INTERFACE 3 588 | #define CDC_IAD_DESCRIPTOR 1 589 | #define CDC_STATUS_INTERFACE 0 590 | #define CDC_DATA_INTERFACE 1 // Serial 591 | #define CDC_ACM_ENDPOINT 1 592 | #define CDC_RX_ENDPOINT 2 593 | #define CDC_TX_ENDPOINT 3 594 | #define CDC_ACM_SIZE 16 595 | #define CDC_RX_SIZE 64 596 | #define CDC_TX_SIZE 64 597 | #define MIDI_INTERFACE 2 // MIDI 598 | #define MIDI_NUM_CABLES 16 599 | #define MIDI_TX_ENDPOINT 4 600 | #define MIDI_TX_SIZE 64 601 | #define MIDI_RX_ENDPOINT 5 602 | #define MIDI_RX_SIZE 64 603 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 604 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 605 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 606 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 607 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 608 | 609 | #elif defined(USB_RAWHID) 610 | #define VENDOR_ID 0x16C0 611 | #define PRODUCT_ID 0x0486 612 | #define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF 613 | #define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF 614 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 615 | #define MANUFACTURER_NAME_LEN 11 616 | #define PRODUCT_NAME {'T','e','e','n','s','y','d','u','i','n','o',' ','R','a','w','H','I','D'} 617 | #define PRODUCT_NAME_LEN 18 618 | #define EP0_SIZE 64 619 | #define NUM_ENDPOINTS 4 620 | #define NUM_USB_BUFFERS 12 621 | #define NUM_INTERFACE 2 622 | #define RAWHID_INTERFACE 0 // RawHID 623 | #define RAWHID_TX_ENDPOINT 3 624 | #define RAWHID_TX_SIZE 64 625 | #define RAWHID_TX_INTERVAL 1 626 | #define RAWHID_RX_ENDPOINT 4 627 | #define RAWHID_RX_SIZE 64 628 | #define RAWHID_RX_INTERVAL 1 629 | #define SEREMU_INTERFACE 1 // Serial emulation 630 | #define SEREMU_TX_ENDPOINT 1 631 | #define SEREMU_TX_SIZE 64 632 | #define SEREMU_TX_INTERVAL 1 633 | #define SEREMU_RX_ENDPOINT 2 634 | #define SEREMU_RX_SIZE 32 635 | #define SEREMU_RX_INTERVAL 2 636 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 637 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 638 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 639 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 640 | 641 | #elif defined(USB_FLIGHTSIM) 642 | #define VENDOR_ID 0x16C0 643 | #define PRODUCT_ID 0x0488 644 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 645 | #define MANUFACTURER_NAME_LEN 11 646 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'} 647 | #define PRODUCT_NAME_LEN 26 648 | #define EP0_SIZE 64 649 | #define NUM_ENDPOINTS 4 650 | #define NUM_USB_BUFFERS 20 651 | #define NUM_INTERFACE 2 652 | #define FLIGHTSIM_INTERFACE 0 // Flight Sim Control 653 | #define FLIGHTSIM_TX_ENDPOINT 3 654 | #define FLIGHTSIM_TX_SIZE 64 655 | #define FLIGHTSIM_TX_INTERVAL 1 656 | #define FLIGHTSIM_RX_ENDPOINT 4 657 | #define FLIGHTSIM_RX_SIZE 64 658 | #define FLIGHTSIM_RX_INTERVAL 1 659 | #define SEREMU_INTERFACE 1 // Serial emulation 660 | #define SEREMU_TX_ENDPOINT 1 661 | #define SEREMU_TX_SIZE 64 662 | #define SEREMU_TX_INTERVAL 1 663 | #define SEREMU_RX_ENDPOINT 2 664 | #define SEREMU_RX_SIZE 32 665 | #define SEREMU_RX_INTERVAL 2 666 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 667 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 668 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 669 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 670 | 671 | #elif defined(USB_FLIGHTSIM_JOYSTICK) 672 | #define VENDOR_ID 0x16C0 673 | #define PRODUCT_ID 0x0488 674 | #define BCD_DEVICE 0x0211 675 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 676 | #define MANUFACTURER_NAME_LEN 11 677 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'} 678 | #define PRODUCT_NAME_LEN 26 679 | #define EP0_SIZE 64 680 | #define NUM_ENDPOINTS 5 681 | #define NUM_USB_BUFFERS 20 682 | #define NUM_INTERFACE 3 683 | #define FLIGHTSIM_INTERFACE 0 // Flight Sim Control 684 | #define FLIGHTSIM_TX_ENDPOINT 3 685 | #define FLIGHTSIM_TX_SIZE 64 686 | #define FLIGHTSIM_TX_INTERVAL 1 687 | #define FLIGHTSIM_RX_ENDPOINT 4 688 | #define FLIGHTSIM_RX_SIZE 64 689 | #define FLIGHTSIM_RX_INTERVAL 1 690 | #define SEREMU_INTERFACE 1 // Serial emulation 691 | #define SEREMU_TX_ENDPOINT 1 692 | #define SEREMU_TX_SIZE 64 693 | #define SEREMU_TX_INTERVAL 1 694 | #define SEREMU_RX_ENDPOINT 2 695 | #define SEREMU_RX_SIZE 32 696 | #define SEREMU_RX_INTERVAL 2 697 | #define JOYSTICK_INTERFACE 2 // Joystick 698 | #define JOYSTICK_ENDPOINT 5 699 | #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick 700 | #define JOYSTICK_INTERVAL 1 701 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 702 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 703 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 704 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 705 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 706 | 707 | 708 | #elif defined(USB_MTPDISK) 709 | #define VENDOR_ID 0x16C0 710 | #define PRODUCT_ID 0x04D1 711 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 712 | #define MANUFACTURER_NAME_LEN 11 713 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','T','P',' ','D','i','s','k'} 714 | #define PRODUCT_NAME_LEN 15 715 | #define EP0_SIZE 64 716 | #define NUM_ENDPOINTS 4 717 | #define NUM_USB_BUFFERS 20 718 | #define NUM_INTERFACE 2 719 | #define MTP_INTERFACE 0 // MTP Disk 720 | #define MTP_TX_ENDPOINT 3 721 | #define MTP_TX_SIZE 64 722 | #define MTP_RX_ENDPOINT 3 723 | #define MTP_RX_SIZE 64 724 | #define MTP_EVENT_ENDPOINT 4 725 | #define MTP_EVENT_SIZE 32 726 | #define MTP_EVENT_INTERVAL 10 727 | #define SEREMU_INTERFACE 1 // Serial emulation 728 | #define SEREMU_TX_ENDPOINT 1 729 | #define SEREMU_TX_SIZE 64 730 | #define SEREMU_TX_INTERVAL 1 731 | #define SEREMU_RX_ENDPOINT 2 732 | #define SEREMU_RX_SIZE 32 733 | #define SEREMU_RX_INTERVAL 2 734 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 735 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 736 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 737 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 738 | 739 | #elif defined(USB_MTPDISK_SERIAL) 740 | #define VENDOR_ID 0x16C0 741 | #define PRODUCT_ID 0x04D5 742 | #define DEVICE_CLASS 0xEF 743 | #define DEVICE_SUBCLASS 0x02 744 | #define DEVICE_PROTOCOL 0x01 745 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 746 | #define MANUFACTURER_NAME_LEN 11 747 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','T','P',' ','D','i','s','k'} 748 | #define PRODUCT_NAME_LEN 15 749 | #define EP0_SIZE 64 750 | 751 | #define NUM_ENDPOINTS 6 752 | #define NUM_USB_BUFFERS 20 753 | #define NUM_INTERFACE 3 754 | 755 | #define CDC_IAD_DESCRIPTOR 1 756 | #define CDC_STATUS_INTERFACE 0 757 | #define CDC_DATA_INTERFACE 1 // Serial 758 | #define CDC_ACM_ENDPOINT 1 759 | #define CDC_RX_ENDPOINT 2 760 | #define CDC_TX_ENDPOINT 3 761 | #define CDC_ACM_SIZE 16 762 | #define CDC_RX_SIZE 64 763 | #define CDC_TX_SIZE 64 764 | 765 | #define MTP_INTERFACE 2 // MTP Disk 766 | #define MTP_TX_ENDPOINT 4 767 | #define MTP_TX_SIZE 64 768 | #define MTP_RX_ENDPOINT 5 769 | #define MTP_RX_SIZE 64 770 | #define MTP_EVENT_ENDPOINT 6 771 | #define MTP_EVENT_SIZE 32 772 | #define MTP_EVENT_INTERVAL 10 773 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 774 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 775 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 776 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 777 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 778 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 779 | 780 | #elif defined(USB_AUDIO) 781 | #define VENDOR_ID 0x16C0 782 | #define PRODUCT_ID 0x04D2 783 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 784 | #define MANUFACTURER_NAME_LEN 11 785 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','A','u','d','i','o'} 786 | #define PRODUCT_NAME_LEN 12 787 | #define EP0_SIZE 64 788 | #define NUM_ENDPOINTS 5 789 | #define NUM_USB_BUFFERS 16 790 | #define NUM_INTERFACE 4 791 | #define SEREMU_INTERFACE 0 // Serial emulation 792 | #define SEREMU_TX_ENDPOINT 1 793 | #define SEREMU_TX_SIZE 64 794 | #define SEREMU_TX_INTERVAL 1 795 | #define SEREMU_RX_ENDPOINT 2 796 | #define SEREMU_RX_SIZE 32 797 | #define SEREMU_RX_INTERVAL 2 798 | #define AUDIO_INTERFACE 1 // Audio (uses 3 consecutive interfaces) 799 | #define AUDIO_TX_ENDPOINT 3 800 | #define AUDIO_TX_SIZE 180 801 | #define AUDIO_RX_ENDPOINT 4 802 | #define AUDIO_RX_SIZE 180 803 | #define AUDIO_SYNC_ENDPOINT 5 804 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 805 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 806 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 807 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS 808 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 809 | 810 | #elif defined(USB_MIDI_AUDIO_SERIAL) 811 | #define VENDOR_ID 0x16C0 812 | #define PRODUCT_ID 0x048A 813 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 814 | #define MANUFACTURER_NAME_LEN 11 815 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','/','A','u','d','i','o'} 816 | #define PRODUCT_NAME_LEN 17 817 | #define EP0_SIZE 64 818 | #define NUM_ENDPOINTS 8 819 | #define NUM_USB_BUFFERS 30 820 | #define NUM_INTERFACE 6 821 | #define CDC_IAD_DESCRIPTOR 1 822 | #define CDC_STATUS_INTERFACE 0 823 | #define CDC_DATA_INTERFACE 1 // Serial 824 | #define CDC_ACM_ENDPOINT 1 825 | #define CDC_RX_ENDPOINT 2 826 | #define CDC_TX_ENDPOINT 3 827 | #define CDC_ACM_SIZE 16 828 | #define CDC_RX_SIZE 64 829 | #define CDC_TX_SIZE 64 830 | #define MIDI_INTERFACE 2 // MIDI 831 | #define MIDI_NUM_CABLES 1 832 | #define MIDI_TX_ENDPOINT 4 833 | #define MIDI_TX_SIZE 64 834 | #define MIDI_RX_ENDPOINT 5 835 | #define MIDI_RX_SIZE 64 836 | #define AUDIO_INTERFACE 3 // Audio (uses 3 consecutive interfaces) 837 | #define AUDIO_TX_ENDPOINT 6 838 | #define AUDIO_TX_SIZE 180 839 | #define AUDIO_RX_ENDPOINT 7 840 | #define AUDIO_RX_SIZE 180 841 | #define AUDIO_SYNC_ENDPOINT 8 842 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 843 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 844 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 845 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 846 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 847 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 848 | #define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS 849 | #define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 850 | 851 | #elif defined(USB_MIDI16_AUDIO_SERIAL) 852 | #define VENDOR_ID 0x16C0 853 | #define PRODUCT_ID 0x048A 854 | #define BCD_DEVICE 0x0212 855 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 856 | #define MANUFACTURER_NAME_LEN 11 857 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','1','6','/','A','u','d','i','o'} 858 | #define PRODUCT_NAME_LEN 20 859 | #define EP0_SIZE 64 860 | #define NUM_ENDPOINTS 8 861 | #define NUM_USB_BUFFERS 30 862 | #define NUM_INTERFACE 6 863 | #define CDC_IAD_DESCRIPTOR 1 864 | #define CDC_STATUS_INTERFACE 0 865 | #define CDC_DATA_INTERFACE 1 // Serial 866 | #define CDC_ACM_ENDPOINT 1 867 | #define CDC_RX_ENDPOINT 2 868 | #define CDC_TX_ENDPOINT 3 869 | #define CDC_ACM_SIZE 16 870 | #define CDC_RX_SIZE 64 871 | #define CDC_TX_SIZE 64 872 | #define MIDI_INTERFACE 2 // MIDI 873 | #define MIDI_NUM_CABLES 16 874 | #define MIDI_TX_ENDPOINT 4 875 | #define MIDI_TX_SIZE 64 876 | #define MIDI_RX_ENDPOINT 5 877 | #define MIDI_RX_SIZE 64 878 | #define AUDIO_INTERFACE 3 // Audio (uses 3 consecutive interfaces) 879 | #define AUDIO_TX_ENDPOINT 6 880 | #define AUDIO_TX_SIZE 180 881 | #define AUDIO_RX_ENDPOINT 7 882 | #define AUDIO_RX_SIZE 180 883 | #define AUDIO_SYNC_ENDPOINT 8 884 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 885 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 886 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 887 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 888 | #define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY 889 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 890 | #define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS 891 | #define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 892 | 893 | #elif defined(USB_EVERYTHING) 894 | #define VENDOR_ID 0x16C0 895 | #define PRODUCT_ID 0x0476 896 | #define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF 897 | #define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF 898 | #define DEVICE_CLASS 0xEF 899 | #define DEVICE_SUBCLASS 0x02 900 | #define DEVICE_PROTOCOL 0x01 901 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 902 | #define MANUFACTURER_NAME_LEN 11 903 | #define PRODUCT_NAME {'A','l','l',' ','T','h','e',' ','T','h','i','n','g','s'} 904 | #define PRODUCT_NAME_LEN 14 905 | #define EP0_SIZE 64 906 | #define NUM_ENDPOINTS 15 907 | #define NUM_USB_BUFFERS 31 908 | #define NUM_INTERFACE 13 909 | #define CDC_IAD_DESCRIPTOR 1 910 | #define CDC_STATUS_INTERFACE 0 911 | #define CDC_DATA_INTERFACE 1 // Serial 912 | #define CDC_ACM_ENDPOINT 1 913 | #define CDC_RX_ENDPOINT 2 914 | #define CDC_TX_ENDPOINT 2 915 | #define CDC_ACM_SIZE 16 916 | #define CDC_RX_SIZE 64 917 | #define CDC_TX_SIZE 64 918 | #define MIDI_INTERFACE 2 // MIDI 919 | #define MIDI_NUM_CABLES 16 920 | #define MIDI_TX_ENDPOINT 3 921 | #define MIDI_TX_SIZE 64 922 | #define MIDI_RX_ENDPOINT 3 923 | #define MIDI_RX_SIZE 64 924 | #define KEYBOARD_INTERFACE 3 // Keyboard 925 | #define KEYBOARD_ENDPOINT 4 926 | #define KEYBOARD_SIZE 8 927 | #define KEYBOARD_INTERVAL 1 928 | #define MOUSE_INTERFACE 4 // Mouse 929 | #define MOUSE_ENDPOINT 5 930 | #define MOUSE_SIZE 8 931 | #define MOUSE_INTERVAL 2 932 | #define RAWHID_INTERFACE 5 // RawHID 933 | #define RAWHID_TX_ENDPOINT 6 934 | #define RAWHID_TX_SIZE 64 935 | #define RAWHID_TX_INTERVAL 1 936 | #define RAWHID_RX_ENDPOINT 6 937 | #define RAWHID_RX_SIZE 64 938 | #define RAWHID_RX_INTERVAL 1 939 | #define FLIGHTSIM_INTERFACE 6 // Flight Sim Control 940 | #define FLIGHTSIM_TX_ENDPOINT 9 941 | #define FLIGHTSIM_TX_SIZE 64 942 | #define FLIGHTSIM_TX_INTERVAL 1 943 | #define FLIGHTSIM_RX_ENDPOINT 9 944 | #define FLIGHTSIM_RX_SIZE 64 945 | #define FLIGHTSIM_RX_INTERVAL 1 946 | #define JOYSTICK_INTERFACE 7 // Joystick 947 | #define JOYSTICK_ENDPOINT 10 948 | #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick 949 | #define JOYSTICK_INTERVAL 1 950 | /* 951 | #define MTP_INTERFACE 8 // MTP Disk 952 | #define MTP_TX_ENDPOINT 11 953 | #define MTP_TX_SIZE 64 954 | #define MTP_RX_ENDPOINT 3 955 | #define MTP_RX_SIZE 64 956 | #define MTP_EVENT_ENDPOINT 11 957 | #define MTP_EVENT_SIZE 16 958 | #define MTP_EVENT_INTERVAL 10 959 | */ 960 | #define KEYMEDIA_INTERFACE 8 // Keyboard Media Keys 961 | #define KEYMEDIA_ENDPOINT 12 962 | #define KEYMEDIA_SIZE 8 963 | #define KEYMEDIA_INTERVAL 4 964 | #define AUDIO_INTERFACE 9 // Audio (uses 3 consecutive interfaces) 965 | #define AUDIO_TX_ENDPOINT 13 966 | #define AUDIO_TX_SIZE 180 967 | #define AUDIO_RX_ENDPOINT 13 968 | #define AUDIO_RX_SIZE 180 969 | #define AUDIO_SYNC_ENDPOINT 14 970 | #define MULTITOUCH_INTERFACE 12 // Touchscreen 971 | #define MULTITOUCH_ENDPOINT 15 972 | #define MULTITOUCH_SIZE 8 973 | #define MULTITOUCH_FINGERS 10 974 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 975 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 976 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 977 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY 978 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY 979 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 980 | #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 981 | #define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY 982 | #define ENDPOINT9_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 983 | #define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY 984 | #define ENDPOINT11_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 985 | #define ENDPOINT12_CONFIG ENDPOINT_TRANSMIT_ONLY 986 | #define ENDPOINT13_CONFIG (ENDPOINT_RECEIVE_ISOCHRONOUS|ENDPOINT_TRANSMIT_ISOCHRONOUS) 987 | #define ENDPOINT14_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS 988 | #define ENDPOINT15_CONFIG ENDPOINT_TRANSMIT_ONLY 989 | 990 | #elif defined(USB_XINPUT) 991 | #define DEVICE_CLASS 0xFF 992 | #define DEVICE_SUBCLASS 0xFF 993 | #define DEVICE_PROTOCOL 0xFF 994 | #define BCD_DEVICE 0x0114 995 | #define DEVICE_ATTRIBUTES 0xA0 996 | #define DEVICE_POWER 0xFA 997 | #define VENDOR_ID 0x045e 998 | #define PRODUCT_ID 0x028e 999 | #define MANUFACTURER_NAME {0x00A9,'M','i','c','r','o','s','o','f','t'} 1000 | #define MANUFACTURER_NAME_LEN 10 1001 | #define PRODUCT_NAME {'C','o','n','t','r','o','l','l','e','r'} 1002 | #define PRODUCT_NAME_LEN 10 1003 | #define EP0_SIZE 8 1004 | #define NUM_ENDPOINTS 6 1005 | #define NUM_USB_BUFFERS 24 1006 | #define NUM_INTERFACE 4 1007 | #define XINPUT_INTERFACE 0 1008 | #define XINPUT_RX_ENDPOINT 2 1009 | #define XINPUT_RX_SIZE 8 1010 | #define XINPUT_TX_ENDPOINT 1 1011 | #define XINPUT_TX_SIZE 20 1012 | #define CONFIG_DESC_SIZE 153 1013 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY 1014 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 1015 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY 1016 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 1017 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 1018 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY 1019 | 1020 | 1021 | #endif 1022 | 1023 | #ifdef USB_DESC_LIST_DEFINE 1024 | #if defined(NUM_ENDPOINTS) && NUM_ENDPOINTS > 0 1025 | // NUM_ENDPOINTS = number of non-zero endpoints (0 to 15) 1026 | extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS]; 1027 | 1028 | typedef struct { 1029 | uint16_t wValue; 1030 | uint16_t wIndex; 1031 | const uint8_t *addr; 1032 | uint16_t length; 1033 | } usb_descriptor_list_t; 1034 | 1035 | extern const usb_descriptor_list_t usb_descriptor_list[]; 1036 | #endif // NUM_ENDPOINTS 1037 | #endif // USB_DESC_LIST_DEFINE 1038 | 1039 | #endif 1040 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_dev.c: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | * 30 | * Trying to understand this rather complex code? 31 | * 32 | * Kevin Cuzner wrote a simpler version, and a great blog article: 33 | * http://kevincuzner.com/2014/12/12/teensy-3-1-bare-metal-writing-a-usb-driver/ 34 | * https://github.com/kcuzner/teensy-oscilloscope/blob/master/scope-teensy/src/usb.c 35 | * 36 | * Andy Payne wrote another relatively simple USB example for Freescale Kinetis 37 | * https://github.com/payne92/bare-metal-arm 38 | */ 39 | 40 | #include "usb_dev.h" 41 | #if F_CPU >= 20000000 && defined(NUM_ENDPOINTS) 42 | 43 | #include "kinetis.h" 44 | //#include "HardwareSerial.h" 45 | #include "usb_mem.h" 46 | #include // for memset 47 | 48 | // This code has a known bug with compiled with -O2 optimization on gcc 5.4.1 49 | // https://forum.pjrc.com/threads/53574-Teensyduino-1-43-Beta-2?p=186177&viewfull=1#post186177 50 | #if 0 51 | #if defined(__MKL26Z64__) 52 | #pragma GCC optimize ("Os") 53 | #else 54 | #pragma GCC optimize ("O3") 55 | #endif 56 | #endif 57 | // adding volatile to bdt_t fully solves the bug, right? 58 | // https://forum.pjrc.com/threads/67081?p=278849&viewfull=1#post278849 59 | 60 | // buffer descriptor table 61 | 62 | typedef volatile struct { 63 | uint32_t desc; 64 | void * addr; 65 | } bdt_t; 66 | 67 | __attribute__ ((section(".usbdescriptortable"), used)) 68 | static bdt_t table[(NUM_ENDPOINTS+1)*4]; 69 | 70 | static usb_packet_t *rx_first[NUM_ENDPOINTS]; 71 | static usb_packet_t *rx_last[NUM_ENDPOINTS]; 72 | static usb_packet_t *tx_first[NUM_ENDPOINTS]; 73 | static usb_packet_t *tx_last[NUM_ENDPOINTS]; 74 | uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; 75 | 76 | static uint8_t tx_state[NUM_ENDPOINTS]; 77 | #define TX_STATE_BOTH_FREE_EVEN_FIRST 0 78 | #define TX_STATE_BOTH_FREE_ODD_FIRST 1 79 | #define TX_STATE_EVEN_FREE 2 80 | #define TX_STATE_ODD_FREE 3 81 | #define TX_STATE_NONE_FREE_EVEN_FIRST 4 82 | #define TX_STATE_NONE_FREE_ODD_FIRST 5 83 | 84 | #define BDT_OWN 0x80 85 | #define BDT_DATA1 0x40 86 | #define BDT_DATA0 0x00 87 | #define BDT_DTS 0x08 88 | #define BDT_STALL 0x04 89 | #define BDT_PID(n) (((n) >> 2) & 15) 90 | 91 | #define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \ 92 | | ((data) ? BDT_DATA1 : BDT_DATA0) \ 93 | | ((count) << 16)) 94 | 95 | #define TX 1 96 | #define RX 0 97 | #define ODD 1 98 | #define EVEN 0 99 | #define DATA0 0 100 | #define DATA1 1 101 | #define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) 102 | #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 103 | 104 | 105 | static union { 106 | struct { 107 | union { 108 | struct { 109 | uint8_t bmRequestType; 110 | uint8_t bRequest; 111 | }; 112 | uint16_t wRequestAndType; 113 | }; 114 | uint16_t wValue; 115 | uint16_t wIndex; 116 | uint16_t wLength; 117 | }; 118 | struct { 119 | uint32_t word1; 120 | uint32_t word2; 121 | }; 122 | } setup; 123 | 124 | 125 | #define GET_STATUS 0 126 | #define CLEAR_FEATURE 1 127 | #define SET_FEATURE 3 128 | #define SET_ADDRESS 5 129 | #define GET_DESCRIPTOR 6 130 | #define SET_DESCRIPTOR 7 131 | #define GET_CONFIGURATION 8 132 | #define SET_CONFIGURATION 9 133 | #define GET_INTERFACE 10 134 | #define SET_INTERFACE 11 135 | #define SYNCH_FRAME 12 136 | 137 | // SETUP always uses a DATA0 PID for the data field of the SETUP transaction. 138 | // transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1) 139 | // Status stage uses a DATA1 PID. 140 | 141 | static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4))); 142 | static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4))); 143 | static const uint8_t *ep0_tx_ptr = NULL; 144 | static uint16_t ep0_tx_len; 145 | static uint8_t ep0_tx_bdt_bank = 0; 146 | static uint8_t ep0_tx_data_toggle = 0; 147 | uint8_t usb_rx_memory_needed = 0; 148 | 149 | volatile uint8_t usb_configuration = 0; 150 | volatile uint8_t usb_reboot_timer = 0; 151 | 152 | 153 | static void endpoint0_stall(void) 154 | { 155 | USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 156 | } 157 | 158 | 159 | static void endpoint0_transmit(const void *data, uint32_t len) 160 | { 161 | #if 0 162 | serial_print("tx0:"); 163 | serial_phex32((uint32_t)data); 164 | serial_print(","); 165 | serial_phex16(len); 166 | serial_print(ep0_tx_bdt_bank ? ", odd" : ", even"); 167 | serial_print(ep0_tx_data_toggle ? ", d1\n" : ", d0\n"); 168 | #endif 169 | table[index(0, TX, ep0_tx_bdt_bank)].addr = (void *)data; 170 | table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle); 171 | ep0_tx_data_toggle ^= 1; 172 | ep0_tx_bdt_bank ^= 1; 173 | } 174 | 175 | static uint8_t reply_buffer[8]; 176 | 177 | static void usb_setup(void) 178 | { 179 | const uint8_t *data = NULL; 180 | uint32_t datalen = 0; 181 | const usb_descriptor_list_t *list; 182 | uint32_t size; 183 | volatile uint8_t *reg; 184 | uint8_t epconf; 185 | const uint8_t *cfg; 186 | int i; 187 | 188 | switch (setup.wRequestAndType) { 189 | case 0x0500: // SET_ADDRESS 190 | break; 191 | case 0x0900: // SET_CONFIGURATION 192 | //serial_print("configure\n"); 193 | usb_configuration = setup.wValue; 194 | reg = &USB0_ENDPT1; 195 | cfg = usb_endpoint_config_table; 196 | // clear all BDT entries, free any allocated memory... 197 | for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) { 198 | if (table[i].desc & BDT_OWN) { 199 | usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8)); 200 | } 201 | } 202 | // free all queued packets 203 | for (i=0; i < NUM_ENDPOINTS; i++) { 204 | usb_packet_t *p, *n; 205 | p = rx_first[i]; 206 | while (p) { 207 | n = p->next; 208 | usb_free(p); 209 | p = n; 210 | } 211 | rx_first[i] = NULL; 212 | rx_last[i] = NULL; 213 | p = tx_first[i]; 214 | while (p) { 215 | n = p->next; 216 | usb_free(p); 217 | p = n; 218 | } 219 | tx_first[i] = NULL; 220 | tx_last[i] = NULL; 221 | usb_rx_byte_count_data[i] = 0; 222 | switch (tx_state[i]) { 223 | case TX_STATE_EVEN_FREE: 224 | case TX_STATE_NONE_FREE_EVEN_FIRST: 225 | tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST; 226 | break; 227 | case TX_STATE_ODD_FREE: 228 | case TX_STATE_NONE_FREE_ODD_FIRST: 229 | tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST; 230 | break; 231 | default: 232 | break; 233 | } 234 | } 235 | usb_rx_memory_needed = 0; 236 | for (i=1; i <= NUM_ENDPOINTS; i++) { 237 | epconf = *cfg++; 238 | *reg = epconf; 239 | reg += 4; 240 | #ifdef AUDIO_INTERFACE 241 | if (i == AUDIO_RX_ENDPOINT) { 242 | table[index(i, RX, EVEN)].addr = usb_audio_receive_buffer; 243 | table[index(i, RX, EVEN)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN; 244 | table[index(i, RX, ODD)].addr = usb_audio_receive_buffer; 245 | table[index(i, RX, ODD)].desc = (AUDIO_RX_SIZE<<16) | BDT_OWN; 246 | } else 247 | #endif 248 | if (epconf & USB_ENDPT_EPRXEN) { 249 | usb_packet_t *p; 250 | p = usb_malloc(); 251 | if (p) { 252 | table[index(i, RX, EVEN)].addr = p->buf; 253 | table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); 254 | } else { 255 | table[index(i, RX, EVEN)].desc = 0; 256 | usb_rx_memory_needed++; 257 | } 258 | p = usb_malloc(); 259 | if (p) { 260 | table[index(i, RX, ODD)].addr = p->buf; 261 | table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); 262 | } else { 263 | table[index(i, RX, ODD)].desc = 0; 264 | usb_rx_memory_needed++; 265 | } 266 | } 267 | table[index(i, TX, EVEN)].desc = 0; 268 | table[index(i, TX, ODD)].desc = 0; 269 | #ifdef AUDIO_INTERFACE 270 | if (i == AUDIO_SYNC_ENDPOINT) { 271 | table[index(i, TX, EVEN)].addr = &usb_audio_sync_feedback; 272 | table[index(i, TX, EVEN)].desc = (3<<16) | BDT_OWN; 273 | } 274 | #endif 275 | } 276 | break; 277 | case 0x0880: // GET_CONFIGURATION 278 | reply_buffer[0] = usb_configuration; 279 | datalen = 1; 280 | data = reply_buffer; 281 | break; 282 | case 0x0080: // GET_STATUS (device) 283 | reply_buffer[0] = 0; 284 | reply_buffer[1] = 0; 285 | datalen = 2; 286 | data = reply_buffer; 287 | break; 288 | case 0x0082: // GET_STATUS (endpoint) 289 | i = setup.wIndex & 0x7F; 290 | if (i > NUM_ENDPOINTS) { 291 | // TODO: do we need to handle IN vs OUT here? 292 | endpoint0_stall(); 293 | return; 294 | } 295 | reply_buffer[0] = 0; 296 | reply_buffer[1] = 0; 297 | if (*(uint8_t *)(&USB0_ENDPT0 + i * 4) & 0x02) reply_buffer[0] = 1; 298 | data = reply_buffer; 299 | datalen = 2; 300 | break; 301 | case 0x0102: // CLEAR_FEATURE (endpoint) 302 | i = setup.wIndex & 0x7F; 303 | if (i > NUM_ENDPOINTS || setup.wValue != 0) { 304 | // TODO: do we need to handle IN vs OUT here? 305 | endpoint0_stall(); 306 | return; 307 | } 308 | (*(uint8_t *)(&USB0_ENDPT0 + i * 4)) &= ~0x02; 309 | // TODO: do we need to clear the data toggle here? 310 | break; 311 | case 0x0302: // SET_FEATURE (endpoint) 312 | i = setup.wIndex & 0x7F; 313 | if (i > NUM_ENDPOINTS || setup.wValue != 0) { 314 | // TODO: do we need to handle IN vs OUT here? 315 | endpoint0_stall(); 316 | return; 317 | } 318 | (*(uint8_t *)(&USB0_ENDPT0 + i * 4)) |= 0x02; 319 | // TODO: do we need to clear the data toggle here? 320 | break; 321 | case 0x0680: // GET_DESCRIPTOR 322 | case 0x0681: 323 | //serial_print("desc:"); 324 | //serial_phex16(setup.wValue); 325 | //serial_print("\n"); 326 | for (list = usb_descriptor_list; 1; list++) { 327 | if (list->addr == NULL) break; 328 | //if (setup.wValue == list->wValue && 329 | //(setup.wIndex == list->wIndex) || ((setup.wValue >> 8) == 3)) { 330 | if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) { 331 | data = list->addr; 332 | if ((setup.wValue >> 8) == 3) { 333 | // for string descriptors, use the descriptor's 334 | // length field, allowing runtime configured 335 | // length. 336 | datalen = *(list->addr); 337 | } else { 338 | datalen = list->length; 339 | } 340 | #if 0 341 | serial_print("Desc found, "); 342 | serial_phex32((uint32_t)data); 343 | serial_print(","); 344 | serial_phex16(datalen); 345 | serial_print(","); 346 | serial_phex(data[0]); 347 | serial_phex(data[1]); 348 | serial_phex(data[2]); 349 | serial_phex(data[3]); 350 | serial_phex(data[4]); 351 | serial_phex(data[5]); 352 | serial_print("\n"); 353 | #endif 354 | goto send; 355 | } 356 | } 357 | //serial_print("desc: not found\n"); 358 | endpoint0_stall(); 359 | return; 360 | case 0x2221: // CDC_SET_CONTROL_LINE_STATE 361 | switch (setup.wIndex) { 362 | #ifdef CDC_STATUS_INTERFACE 363 | case CDC_STATUS_INTERFACE: 364 | usb_cdc_line_rtsdtr_millis = systick_millis_count; 365 | usb_cdc_line_rtsdtr = setup.wValue; 366 | break; 367 | #endif 368 | #ifdef CDC2_STATUS_INTERFACE 369 | case CDC2_STATUS_INTERFACE: 370 | usb_cdc2_line_rtsdtr_millis = systick_millis_count; 371 | usb_cdc2_line_rtsdtr = setup.wValue; 372 | break; 373 | #endif 374 | #ifdef CDC3_STATUS_INTERFACE 375 | case CDC3_STATUS_INTERFACE: 376 | usb_cdc3_line_rtsdtr_millis = systick_millis_count; 377 | usb_cdc3_line_rtsdtr = setup.wValue; 378 | break; 379 | #endif 380 | } 381 | //serial_print("set control line state\n"); 382 | break; 383 | #ifdef CDC_STATUS_INTERFACE 384 | case 0x2321: // CDC_SEND_BREAK 385 | break; 386 | case 0x2021: // CDC_SET_LINE_CODING 387 | //serial_print("set coding, waiting...\n"); 388 | return; 389 | #endif 390 | 391 | #if defined(MTP_INTERFACE) 392 | case 0x64A1: // Cancel Request (PTP spec, 5.2.1, page 8) 393 | // TODO: required by PTP spec 394 | endpoint0_stall(); 395 | return; 396 | case 0x66A1: // Device Reset (PTP spec, 5.2.3, page 10) 397 | // TODO: required by PTP spec 398 | endpoint0_stall(); 399 | return; 400 | case 0x67A1: // Get Device Statis (PTP spec, 5.2.4, page 10) 401 | // For now, always respond with status ok. 402 | reply_buffer[0] = 0x4; 403 | reply_buffer[1] = 0; 404 | reply_buffer[2] = 0x01; 405 | reply_buffer[3] = 0x20; 406 | data = reply_buffer; 407 | datalen = 4; 408 | break; 409 | #endif 410 | 411 | // TODO: this does not work... why? 412 | #if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE) 413 | case 0x0921: // HID SET_REPORT 414 | //serial_print(":)\n"); 415 | return; 416 | case 0x0A21: // HID SET_IDLE 417 | break; 418 | // case 0xC940: 419 | #endif 420 | 421 | #if defined(AUDIO_INTERFACE) 422 | case 0x0B01: // SET_INTERFACE (alternate setting) 423 | if (setup.wIndex == AUDIO_INTERFACE+1) { 424 | usb_audio_transmit_setting = setup.wValue; 425 | if (usb_audio_transmit_setting > 0) { 426 | bdt_t *b = &table[index(AUDIO_TX_ENDPOINT, TX, EVEN)]; 427 | uint8_t state = tx_state[AUDIO_TX_ENDPOINT-1]; 428 | if (state) b++; 429 | if (!(b->desc & BDT_OWN)) { 430 | memset(usb_audio_transmit_buffer, 0, 176); 431 | b->addr = usb_audio_transmit_buffer; 432 | b->desc = (176 << 16) | BDT_OWN; 433 | tx_state[AUDIO_TX_ENDPOINT-1] = state ^ 1; 434 | } 435 | } 436 | } else if (setup.wIndex == AUDIO_INTERFACE+2) { 437 | usb_audio_receive_setting = setup.wValue; 438 | } else { 439 | endpoint0_stall(); 440 | return; 441 | } 442 | break; 443 | case 0x0A81: // GET_INTERFACE (alternate setting) 444 | datalen = 1; 445 | data = reply_buffer; 446 | if (setup.wIndex == AUDIO_INTERFACE+1) { 447 | reply_buffer[0] = usb_audio_transmit_setting; 448 | } else if (setup.wIndex == AUDIO_INTERFACE+2) { 449 | reply_buffer[0] = usb_audio_receive_setting; 450 | } else { 451 | endpoint0_stall(); 452 | return; 453 | } 454 | break; 455 | case 0x0121: // SET FEATURE 456 | case 0x0221: 457 | case 0x0321: 458 | case 0x0421: 459 | // handle these on the next packet. See usb_audio_set_feature() 460 | return; 461 | case 0x81A1: // GET FEATURE 462 | case 0x82A1: 463 | case 0x83A1: 464 | case 0x84A1: 465 | if (usb_audio_get_feature(&setup, reply_buffer, &datalen)) { 466 | data = reply_buffer; 467 | } 468 | else { 469 | endpoint0_stall(); 470 | return; 471 | } 472 | break; 473 | 474 | case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len) 475 | if (setup.wLength >= 3) { 476 | reply_buffer[0] = 44100 & 255; 477 | reply_buffer[1] = 44100 >> 8; 478 | reply_buffer[2] = 0; 479 | datalen = 3; 480 | data = reply_buffer; 481 | } else { 482 | endpoint0_stall(); 483 | return; 484 | } 485 | break; 486 | #endif 487 | 488 | #if defined(MULTITOUCH_INTERFACE) 489 | case 0x01A1: 490 | if (setup.wValue == 0x0300 && setup.wIndex == MULTITOUCH_INTERFACE) { 491 | reply_buffer[0] = MULTITOUCH_FINGERS; 492 | data = reply_buffer; 493 | datalen = 1; 494 | } else if (setup.wValue == 0x0100 && setup.wIndex == MULTITOUCH_INTERFACE) { 495 | memset(reply_buffer, 0, 8); 496 | data = reply_buffer; 497 | datalen = 8; 498 | } else { 499 | endpoint0_stall(); 500 | return; 501 | } 502 | break; 503 | #endif 504 | default: 505 | endpoint0_stall(); 506 | return; 507 | } 508 | send: 509 | //serial_print("setup send "); 510 | //serial_phex32(data); 511 | //serial_print(","); 512 | //serial_phex16(datalen); 513 | //serial_print("\n"); 514 | 515 | if (datalen > setup.wLength) datalen = setup.wLength; 516 | size = datalen; 517 | if (size > EP0_SIZE) size = EP0_SIZE; 518 | endpoint0_transmit(data, size); 519 | data += size; 520 | datalen -= size; 521 | if (datalen == 0 && size < EP0_SIZE) return; 522 | 523 | size = datalen; 524 | if (size > EP0_SIZE) size = EP0_SIZE; 525 | endpoint0_transmit(data, size); 526 | data += size; 527 | datalen -= size; 528 | if (datalen == 0 && size < EP0_SIZE) return; 529 | 530 | ep0_tx_ptr = data; 531 | ep0_tx_len = datalen; 532 | } 533 | 534 | 535 | 536 | //A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint 537 | //experiences any configuration event (configuration events are explained in 538 | //Sections 9.1.1.5 and 9.4.5). 539 | 540 | //Configuring a device or changing an alternate setting causes all of the status 541 | //and configuration values associated with endpoints in the affected interfaces 542 | //to be set to their default values. This includes setting the data toggle of 543 | //any endpoint using data toggles to the value DATA0. 544 | 545 | //For endpoints using data toggle, regardless of whether an endpoint has the 546 | //Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the 547 | //data toggle being reinitialized to DATA0. 548 | 549 | 550 | 551 | // #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 552 | 553 | static void usb_control(uint32_t stat) 554 | { 555 | bdt_t *b; 556 | uint32_t pid, size; 557 | uint8_t *buf; 558 | const uint8_t *data; 559 | 560 | b = stat2bufferdescriptor(stat); 561 | pid = BDT_PID(b->desc); 562 | //count = b->desc >> 16; 563 | buf = b->addr; 564 | //serial_print("pid:"); 565 | //serial_phex(pid); 566 | //serial_print(", count:"); 567 | //serial_phex(count); 568 | //serial_print("\n"); 569 | 570 | switch (pid) { 571 | case 0x0D: // Setup received from host 572 | //serial_print("PID=Setup\n"); 573 | //if (count != 8) ; // panic? 574 | // grab the 8 byte setup info 575 | setup.word1 = *(uint32_t *)(buf); 576 | setup.word2 = *(uint32_t *)(buf + 4); 577 | 578 | // give the buffer back 579 | b->desc = BDT_DESC(EP0_SIZE, DATA1); 580 | //table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 1); 581 | //table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 1); 582 | 583 | // clear any leftover pending IN transactions 584 | ep0_tx_ptr = NULL; 585 | if (ep0_tx_data_toggle) { 586 | } 587 | //if (table[index(0, TX, EVEN)].desc & 0x80) { 588 | //serial_print("leftover tx even\n"); 589 | //} 590 | //if (table[index(0, TX, ODD)].desc & 0x80) { 591 | //serial_print("leftover tx odd\n"); 592 | //} 593 | table[index(0, TX, EVEN)].desc = 0; 594 | table[index(0, TX, ODD)].desc = 0; 595 | // first IN after Setup is always DATA1 596 | ep0_tx_data_toggle = 1; 597 | 598 | #if 0 599 | serial_print("bmRequestType:"); 600 | serial_phex(setup.bmRequestType); 601 | serial_print(", bRequest:"); 602 | serial_phex(setup.bRequest); 603 | serial_print(", wValue:"); 604 | serial_phex16(setup.wValue); 605 | serial_print(", wIndex:"); 606 | serial_phex16(setup.wIndex); 607 | serial_print(", len:"); 608 | serial_phex16(setup.wLength); 609 | serial_print("\n"); 610 | #endif 611 | // actually "do" the setup request 612 | usb_setup(); 613 | // unfreeze the USB, now that we're ready 614 | USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit 615 | break; 616 | case 0x01: // OUT transaction received from host 617 | case 0x02: 618 | //serial_print("PID=OUT\n"); 619 | if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) { 620 | int i; 621 | uint32_t *line_coding = NULL; 622 | switch (setup.wIndex) { 623 | #ifdef CDC_STATUS_INTERFACE 624 | case CDC_STATUS_INTERFACE: 625 | line_coding = usb_cdc_line_coding; 626 | break; 627 | #endif 628 | #ifdef CDC2_STATUS_INTERFACE 629 | case CDC2_STATUS_INTERFACE: 630 | line_coding = usb_cdc2_line_coding; 631 | break; 632 | #endif 633 | #ifdef CDC3_STATUS_INTERFACE 634 | case CDC3_STATUS_INTERFACE: 635 | line_coding = usb_cdc3_line_coding; 636 | break; 637 | #endif 638 | } 639 | if (line_coding) { 640 | uint8_t *dst = (uint8_t *)line_coding; 641 | //serial_print("set line coding "); 642 | for (i=0; i<7; i++) { 643 | //serial_phex(*buf); 644 | *dst++ = *buf++; 645 | } 646 | //serial_phex32(line_coding[0]); 647 | //serial_print("\n"); 648 | if (line_coding[0] == 134) usb_reboot_timer = 15; 649 | } 650 | endpoint0_transmit(NULL, 0); 651 | } 652 | #ifdef KEYBOARD_INTERFACE 653 | if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) { 654 | keyboard_leds = buf[0]; 655 | endpoint0_transmit(NULL, 0); 656 | } 657 | #endif 658 | #ifdef SEREMU_INTERFACE 659 | if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE)) { 660 | if (buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) { 661 | usb_reboot_timer = 5; 662 | } else { 663 | usb_seremu_online = 1; 664 | } 665 | endpoint0_transmit(NULL, 0); 666 | } 667 | #endif 668 | #ifdef AUDIO_INTERFACE 669 | if (usb_audio_set_feature(&setup, buf)) { 670 | endpoint0_transmit(NULL, 0); 671 | } 672 | #endif 673 | // give the buffer back 674 | b->desc = BDT_DESC(EP0_SIZE, DATA1); 675 | break; 676 | 677 | case 0x09: // IN transaction completed to host 678 | //serial_print("PID=IN:"); 679 | //serial_phex(stat); 680 | //serial_print("\n"); 681 | 682 | // send remaining data, if any... 683 | data = ep0_tx_ptr; 684 | if (data) { 685 | size = ep0_tx_len; 686 | if (size > EP0_SIZE) size = EP0_SIZE; 687 | endpoint0_transmit(data, size); 688 | data += size; 689 | ep0_tx_len -= size; 690 | ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL; 691 | } 692 | 693 | if (setup.bRequest == 5 && setup.bmRequestType == 0) { 694 | setup.bRequest = 0; 695 | //serial_print("set address: "); 696 | //serial_phex16(setup.wValue); 697 | //serial_print("\n"); 698 | USB0_ADDR = setup.wValue; 699 | } 700 | 701 | break; 702 | //default: 703 | //serial_print("PID=unknown:"); 704 | //serial_phex(pid); 705 | //serial_print("\n"); 706 | } 707 | USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit 708 | } 709 | 710 | 711 | 712 | 713 | 714 | 715 | usb_packet_t *usb_rx(uint32_t endpoint) 716 | { 717 | usb_packet_t *ret; 718 | endpoint--; 719 | if (endpoint >= NUM_ENDPOINTS) return NULL; 720 | __disable_irq(); 721 | ret = rx_first[endpoint]; 722 | if (ret) { 723 | rx_first[endpoint] = ret->next; 724 | usb_rx_byte_count_data[endpoint] -= ret->len; 725 | } 726 | __enable_irq(); 727 | //serial_print("rx, epidx="); 728 | //serial_phex(endpoint); 729 | //serial_print(", packet="); 730 | //serial_phex32(ret); 731 | //serial_print("\n"); 732 | return ret; 733 | } 734 | 735 | static uint32_t usb_queue_byte_count(const usb_packet_t *p) 736 | { 737 | uint32_t count=0; 738 | 739 | __disable_irq(); 740 | for ( ; p; p = p->next) { 741 | count += p->len; 742 | } 743 | __enable_irq(); 744 | return count; 745 | } 746 | 747 | // TODO: make this an inline function... 748 | /* 749 | uint32_t usb_rx_byte_count(uint32_t endpoint) 750 | { 751 | endpoint--; 752 | if (endpoint >= NUM_ENDPOINTS) return 0; 753 | return usb_rx_byte_count_data[endpoint]; 754 | //return usb_queue_byte_count(rx_first[endpoint]); 755 | } 756 | */ 757 | 758 | uint32_t usb_tx_byte_count(uint32_t endpoint) 759 | { 760 | endpoint--; 761 | if (endpoint >= NUM_ENDPOINTS) return 0; 762 | return usb_queue_byte_count(tx_first[endpoint]); 763 | } 764 | 765 | // Discussion about using this function and USB transmit latency 766 | // https://forum.pjrc.com/threads/58663?p=223513&viewfull=1#post223513 767 | // 768 | uint32_t usb_tx_packet_count(uint32_t endpoint) 769 | { 770 | const usb_packet_t *p; 771 | uint32_t count=0; 772 | 773 | endpoint--; 774 | if (endpoint >= NUM_ENDPOINTS) return 0; 775 | __disable_irq(); 776 | for (p = tx_first[endpoint]; p; p = p->next) count++; 777 | __enable_irq(); 778 | return count; 779 | } 780 | 781 | 782 | // Called from usb_free, but only when usb_rx_memory_needed > 0, indicating 783 | // receive endpoints are starving for memory. The intention is to give 784 | // endpoints needing receive memory priority over the user's code, which is 785 | // likely calling usb_malloc to obtain memory for transmitting. When the 786 | // user is creating data very quickly, their consumption could starve reception 787 | // without this prioritization. The packet buffer (input) is assigned to the 788 | // first endpoint needing memory. 789 | // 790 | void usb_rx_memory(usb_packet_t *packet) 791 | { 792 | unsigned int i; 793 | const uint8_t *cfg; 794 | 795 | cfg = usb_endpoint_config_table; 796 | //serial_print("rx_mem:"); 797 | __disable_irq(); 798 | for (i=1; i <= NUM_ENDPOINTS; i++) { 799 | #ifdef AUDIO_INTERFACE 800 | if (i == AUDIO_RX_ENDPOINT) continue; 801 | #endif 802 | if (*cfg++ & USB_ENDPT_EPRXEN) { 803 | if (table[index(i, RX, EVEN)].desc == 0) { 804 | table[index(i, RX, EVEN)].addr = packet->buf; 805 | table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); 806 | usb_rx_memory_needed--; 807 | __enable_irq(); 808 | //serial_phex(i); 809 | //serial_print(",even\n"); 810 | return; 811 | } 812 | if (table[index(i, RX, ODD)].desc == 0) { 813 | table[index(i, RX, ODD)].addr = packet->buf; 814 | table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); 815 | usb_rx_memory_needed--; 816 | __enable_irq(); 817 | //serial_phex(i); 818 | //serial_print(",odd\n"); 819 | return; 820 | } 821 | } 822 | } 823 | __enable_irq(); 824 | // we should never reach this point. If we get here, it means 825 | // usb_rx_memory_needed was set greater than zero, but no memory 826 | // was actually needed. 827 | usb_rx_memory_needed = 0; 828 | usb_free(packet); 829 | return; 830 | } 831 | 832 | //#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) 833 | //#define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 834 | 835 | void usb_tx(uint32_t endpoint, usb_packet_t *packet) 836 | { 837 | bdt_t *b = &table[index(endpoint, TX, EVEN)]; 838 | uint8_t next; 839 | 840 | endpoint--; 841 | if (endpoint >= NUM_ENDPOINTS) return; 842 | __disable_irq(); 843 | //serial_print("txstate="); 844 | //serial_phex(tx_state[endpoint]); 845 | //serial_print("\n"); 846 | switch (tx_state[endpoint]) { 847 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 848 | next = TX_STATE_ODD_FREE; 849 | break; 850 | case TX_STATE_BOTH_FREE_ODD_FIRST: 851 | b++; 852 | next = TX_STATE_EVEN_FREE; 853 | break; 854 | case TX_STATE_EVEN_FREE: 855 | next = TX_STATE_NONE_FREE_ODD_FIRST; 856 | break; 857 | case TX_STATE_ODD_FREE: 858 | b++; 859 | next = TX_STATE_NONE_FREE_EVEN_FIRST; 860 | break; 861 | default: 862 | if (tx_first[endpoint] == NULL) { 863 | tx_first[endpoint] = packet; 864 | } else { 865 | tx_last[endpoint]->next = packet; 866 | } 867 | tx_last[endpoint] = packet; 868 | __enable_irq(); 869 | return; 870 | } 871 | tx_state[endpoint] = next; 872 | b->addr = packet->buf; 873 | b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); 874 | __enable_irq(); 875 | } 876 | 877 | void usb_tx_isochronous(uint32_t endpoint, void *data, uint32_t len) 878 | { 879 | bdt_t *b = &table[index(endpoint, TX, EVEN)]; 880 | uint8_t next, state; 881 | 882 | endpoint--; 883 | if (endpoint >= NUM_ENDPOINTS) return; 884 | __disable_irq(); 885 | state = tx_state[endpoint]; 886 | if (state == 0) { 887 | next = 1; 888 | } else { 889 | b++; 890 | next = 0; 891 | } 892 | tx_state[endpoint] = next; 893 | b->addr = data; 894 | b->desc = (len << 16) | BDT_OWN; 895 | __enable_irq(); 896 | } 897 | 898 | 899 | 900 | 901 | void _reboot_Teensyduino_(void) 902 | { 903 | // TODO: initialize R0 with a code.... 904 | __asm__ volatile("bkpt"); 905 | __builtin_unreachable(); 906 | } 907 | 908 | 909 | 910 | void usb_isr(void) 911 | { 912 | uint8_t status, stat, t; 913 | 914 | //serial_print("isr"); 915 | //status = USB0_ISTAT; 916 | //serial_phex(status); 917 | //serial_print("\n"); 918 | restart: 919 | status = USB0_ISTAT; 920 | 921 | if ((status & USB_ISTAT_SOFTOK /* 04 */ )) { 922 | if (usb_configuration) { 923 | t = usb_reboot_timer; 924 | if (t) { 925 | usb_reboot_timer = --t; 926 | if (!t) _reboot_Teensyduino_(); 927 | } 928 | #ifdef CDC_DATA_INTERFACE 929 | t = usb_cdc_transmit_flush_timer; 930 | if (t) { 931 | usb_cdc_transmit_flush_timer = --t; 932 | if (t == 0) usb_serial_flush_callback(); 933 | } 934 | #endif 935 | #ifdef CDC2_DATA_INTERFACE 936 | t = usb_cdc2_transmit_flush_timer; 937 | if (t) { 938 | usb_cdc2_transmit_flush_timer = --t; 939 | if (t == 0) usb_serial2_flush_callback(); 940 | } 941 | #endif 942 | #ifdef CDC3_DATA_INTERFACE 943 | t = usb_cdc3_transmit_flush_timer; 944 | if (t) { 945 | usb_cdc3_transmit_flush_timer = --t; 946 | if (t == 0) usb_serial3_flush_callback(); 947 | } 948 | #endif 949 | #ifdef SEREMU_INTERFACE 950 | t = usb_seremu_transmit_flush_timer; 951 | if (t) { 952 | usb_seremu_transmit_flush_timer = --t; 953 | if (t == 0) usb_seremu_flush_callback(); 954 | } 955 | #endif 956 | #ifdef MIDI_INTERFACE 957 | usb_midi_flush_output(); 958 | #endif 959 | #ifdef FLIGHTSIM_INTERFACE 960 | usb_flightsim_flush_callback(); 961 | #endif 962 | #ifdef MULTITOUCH_INTERFACE 963 | usb_touchscreen_update_callback(); 964 | #endif 965 | } 966 | USB0_ISTAT = USB_ISTAT_SOFTOK; 967 | } 968 | 969 | if ((status & USB_ISTAT_TOKDNE /* 08 */ )) { 970 | uint8_t endpoint; 971 | stat = USB0_STAT; 972 | //serial_print("token: ep="); 973 | //serial_phex(stat >> 4); 974 | //serial_print(stat & 0x08 ? ",tx" : ",rx"); 975 | //serial_print(stat & 0x04 ? ",odd\n" : ",even\n"); 976 | endpoint = stat >> 4; 977 | if (endpoint == 0) { 978 | usb_control(stat); 979 | } else { 980 | bdt_t *b = stat2bufferdescriptor(stat); 981 | usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8); 982 | #if 0 983 | serial_print("ep:"); 984 | serial_phex(endpoint); 985 | serial_print(", pid:"); 986 | serial_phex(BDT_PID(b->desc)); 987 | serial_print(((uint32_t)b & 8) ? ", odd" : ", even"); 988 | serial_print(", count:"); 989 | serial_phex(b->desc >> 16); 990 | serial_print("\n"); 991 | #endif 992 | endpoint--; // endpoint is index to zero-based arrays 993 | 994 | #ifdef AUDIO_INTERFACE 995 | if ((endpoint == AUDIO_TX_ENDPOINT-1) && (stat & 0x08)) { 996 | unsigned int len; 997 | len = usb_audio_transmit_callback(); 998 | if (len > 0) { 999 | b = (bdt_t *)((uint32_t)b ^ 8); 1000 | b->addr = usb_audio_transmit_buffer; 1001 | b->desc = (len << 16) | BDT_OWN; 1002 | tx_state[endpoint] ^= 1; 1003 | } 1004 | } else if ((endpoint == AUDIO_RX_ENDPOINT-1) && !(stat & 0x08)) { 1005 | usb_audio_receive_callback(b->desc >> 16); 1006 | b->addr = usb_audio_receive_buffer; 1007 | b->desc = (AUDIO_RX_SIZE << 16) | BDT_OWN; 1008 | } else if ((endpoint == AUDIO_SYNC_ENDPOINT-1) && (stat & 0x08)) { 1009 | b = (bdt_t *)((uint32_t)b ^ 8); 1010 | b->addr = &usb_audio_sync_feedback; 1011 | b->desc = (3 << 16) | BDT_OWN; 1012 | tx_state[endpoint] ^= 1; 1013 | } else 1014 | #endif 1015 | if (stat & 0x08) { // transmit 1016 | usb_free(packet); 1017 | packet = tx_first[endpoint]; 1018 | if (packet) { 1019 | //serial_print("tx packet\n"); 1020 | tx_first[endpoint] = packet->next; 1021 | b->addr = packet->buf; 1022 | switch (tx_state[endpoint]) { 1023 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 1024 | tx_state[endpoint] = TX_STATE_ODD_FREE; 1025 | break; 1026 | case TX_STATE_BOTH_FREE_ODD_FIRST: 1027 | tx_state[endpoint] = TX_STATE_EVEN_FREE; 1028 | break; 1029 | case TX_STATE_EVEN_FREE: 1030 | tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST; 1031 | break; 1032 | case TX_STATE_ODD_FREE: 1033 | tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST; 1034 | break; 1035 | default: 1036 | break; 1037 | } 1038 | b->desc = BDT_DESC(packet->len, 1039 | ((uint32_t)b & 8) ? DATA1 : DATA0); 1040 | } else { 1041 | //serial_print("tx no packet\n"); 1042 | switch (tx_state[endpoint]) { 1043 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 1044 | case TX_STATE_BOTH_FREE_ODD_FIRST: 1045 | break; 1046 | case TX_STATE_EVEN_FREE: 1047 | tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST; 1048 | break; 1049 | case TX_STATE_ODD_FREE: 1050 | tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST; 1051 | break; 1052 | default: 1053 | tx_state[endpoint] = ((uint32_t)b & 8) ? 1054 | TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE; 1055 | break; 1056 | } 1057 | } 1058 | } else { // receive 1059 | packet->len = b->desc >> 16; 1060 | if (packet->len > 0) { 1061 | packet->index = 0; 1062 | packet->next = NULL; 1063 | if (rx_first[endpoint] == NULL) { 1064 | //serial_print("rx 1st, epidx="); 1065 | //serial_phex(endpoint); 1066 | //serial_print(", packet="); 1067 | //serial_phex32((uint32_t)packet); 1068 | //serial_print("\n"); 1069 | rx_first[endpoint] = packet; 1070 | } else { 1071 | //serial_print("rx Nth, epidx="); 1072 | //serial_phex(endpoint); 1073 | //serial_print(", packet="); 1074 | //serial_phex32((uint32_t)packet); 1075 | //serial_print("\n"); 1076 | rx_last[endpoint]->next = packet; 1077 | } 1078 | rx_last[endpoint] = packet; 1079 | usb_rx_byte_count_data[endpoint] += packet->len; 1080 | // TODO: implement a per-endpoint maximum # of allocated 1081 | // packets, so a flood of incoming data on 1 endpoint 1082 | // doesn't starve the others if the user isn't reading 1083 | // it regularly 1084 | packet = usb_malloc(); 1085 | if (packet) { 1086 | b->addr = packet->buf; 1087 | b->desc = BDT_DESC(64, 1088 | ((uint32_t)b & 8) ? DATA1 : DATA0); 1089 | } else { 1090 | //serial_print("starving "); 1091 | //serial_phex(endpoint + 1); 1092 | b->desc = 0; 1093 | usb_rx_memory_needed++; 1094 | } 1095 | } else { 1096 | b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); 1097 | } 1098 | } 1099 | 1100 | #ifdef XINPUT_INTERFACE 1101 | // On receipt of control packet, call XInput receive callback 1102 | if((endpoint == XINPUT_RX_ENDPOINT - 1) && !(stat & 0x08)) { 1103 | if(usb_xinput_recv_callback != NULL) { usb_xinput_recv_callback(); } 1104 | } 1105 | #endif 1106 | 1107 | } 1108 | USB0_ISTAT = USB_ISTAT_TOKDNE; 1109 | goto restart; 1110 | } 1111 | 1112 | 1113 | 1114 | if (status & USB_ISTAT_USBRST /* 01 */ ) { 1115 | //serial_print("reset\n"); 1116 | 1117 | // initialize BDT toggle bits 1118 | USB0_CTL = USB_CTL_ODDRST; 1119 | ep0_tx_bdt_bank = 0; 1120 | 1121 | // set up buffers to receive Setup and OUT packets 1122 | table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0); 1123 | table[index(0, RX, EVEN)].addr = ep0_rx0_buf; 1124 | table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0); 1125 | table[index(0, RX, ODD)].addr = ep0_rx1_buf; 1126 | table[index(0, TX, EVEN)].desc = 0; 1127 | table[index(0, TX, ODD)].desc = 0; 1128 | 1129 | // activate endpoint 0 1130 | USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 1131 | 1132 | // clear all ending interrupts 1133 | USB0_ERRSTAT = 0xFF; 1134 | USB0_ISTAT = 0xFF; 1135 | 1136 | // set the address to zero during enumeration 1137 | USB0_ADDR = 0; 1138 | 1139 | // enable other interrupts 1140 | USB0_ERREN = 0xFF; 1141 | USB0_INTEN = USB_INTEN_TOKDNEEN | 1142 | USB_INTEN_SOFTOKEN | 1143 | USB_INTEN_STALLEN | 1144 | USB_INTEN_ERROREN | 1145 | USB_INTEN_USBRSTEN | 1146 | USB_INTEN_SLEEPEN; 1147 | 1148 | // is this necessary? 1149 | USB0_CTL = USB_CTL_USBENSOFEN; 1150 | return; 1151 | } 1152 | 1153 | 1154 | if ((status & USB_ISTAT_STALL /* 80 */ )) { 1155 | //serial_print("stall:\n"); 1156 | USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 1157 | USB0_ISTAT = USB_ISTAT_STALL; 1158 | } 1159 | if ((status & USB_ISTAT_ERROR /* 02 */ )) { 1160 | uint8_t err = USB0_ERRSTAT; 1161 | USB0_ERRSTAT = err; 1162 | //serial_print("err:"); 1163 | //serial_phex(err); 1164 | //serial_print("\n"); 1165 | USB0_ISTAT = USB_ISTAT_ERROR; 1166 | } 1167 | 1168 | if ((status & USB_ISTAT_SLEEP /* 10 */ )) { 1169 | //serial_print("sleep\n"); 1170 | USB0_ISTAT = USB_ISTAT_SLEEP; 1171 | } 1172 | 1173 | } 1174 | 1175 | 1176 | 1177 | void usb_init(void) 1178 | { 1179 | int i; 1180 | 1181 | //serial_begin(BAUD2DIV(115200)); 1182 | //serial_print("usb_init\n"); 1183 | 1184 | usb_init_serialnumber(); 1185 | 1186 | for (i=0; i < (NUM_ENDPOINTS+1)*4; i++) { 1187 | table[i].desc = 0; 1188 | table[i].addr = 0; 1189 | } 1190 | 1191 | // this basically follows the flowchart in the Kinetis 1192 | // Quick Reference User Guide, Rev. 1, 03/2012, page 141 1193 | 1194 | // assume 48 MHz clock already running 1195 | // SIM - enable clock 1196 | SIM_SCGC4 |= SIM_SCGC4_USBOTG; 1197 | #ifdef HAS_KINETIS_MPU 1198 | MPU_RGDAAC0 |= 0x03000000; 1199 | #endif 1200 | #if F_CPU == 180000000 || F_CPU == 216000000 || F_CPU == 256000000 1201 | // if using IRC48M, turn on the USB clock recovery hardware 1202 | USB0_CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN | USB_CLK_RECOVER_IRC_EN_REG_EN; 1203 | USB0_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN | 1204 | USB_CLK_RECOVER_CTRL_RESTART_IFRTRIM_EN; 1205 | #endif 1206 | // reset USB module 1207 | //USB0_USBTRC0 = USB_USBTRC_USBRESET; 1208 | //while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end 1209 | 1210 | // set desc table base addr 1211 | USB0_BDTPAGE1 = ((uint32_t)table) >> 8; 1212 | USB0_BDTPAGE2 = ((uint32_t)table) >> 16; 1213 | USB0_BDTPAGE3 = ((uint32_t)table) >> 24; 1214 | 1215 | // clear all ISR flags 1216 | USB0_ISTAT = 0xFF; 1217 | USB0_ERRSTAT = 0xFF; 1218 | USB0_OTGISTAT = 0xFF; 1219 | 1220 | //USB0_USBTRC0 |= 0x40; // undocumented bit 1221 | 1222 | // enable USB 1223 | USB0_CTL = USB_CTL_USBENSOFEN; 1224 | USB0_USBCTRL = 0; 1225 | 1226 | // enable reset interrupt 1227 | USB0_INTEN = USB_INTEN_USBRSTEN; 1228 | 1229 | // enable interrupt in NVIC... 1230 | NVIC_SET_PRIORITY(IRQ_USBOTG, 112); 1231 | NVIC_ENABLE_IRQ(IRQ_USBOTG); 1232 | 1233 | // enable d+ pullup 1234 | USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; 1235 | } 1236 | 1237 | 1238 | #else // F_CPU < 20 MHz && defined(NUM_ENDPOINTS) 1239 | 1240 | void usb_init(void) 1241 | { 1242 | } 1243 | 1244 | #endif // F_CPU >= 20 MHz && defined(NUM_ENDPOINTS) 1245 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_dev.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #ifndef _usb_dev_h_ 32 | #define _usb_dev_h_ 33 | 34 | #define USB_DESC_LIST_DEFINE 35 | #include "usb_desc.h" 36 | 37 | #if F_CPU >= 20000000 && !defined(USB_DISABLED) 38 | 39 | // This header is NOT meant to be included when compiling 40 | // user sketches in Arduino. The low-level functions 41 | // provided by usb_dev.c are meant to be called only by 42 | // code which provides higher-level interfaces to the user. 43 | 44 | #include "usb_mem.h" 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | void usb_init(void); 51 | void usb_init_serialnumber(void); 52 | void usb_isr(void); 53 | usb_packet_t *usb_rx(uint32_t endpoint); 54 | uint32_t usb_tx_byte_count(uint32_t endpoint); 55 | uint32_t usb_tx_packet_count(uint32_t endpoint); 56 | void usb_tx(uint32_t endpoint, usb_packet_t *packet); 57 | void usb_tx_isochronous(uint32_t endpoint, void *data, uint32_t len); 58 | 59 | extern volatile uint8_t usb_configuration; 60 | 61 | extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; 62 | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline)); 63 | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) 64 | { 65 | endpoint--; 66 | if (endpoint >= NUM_ENDPOINTS) return 0; 67 | return usb_rx_byte_count_data[endpoint]; 68 | } 69 | 70 | #ifdef SEREMU_INTERFACE 71 | extern volatile uint8_t usb_seremu_transmit_flush_timer; 72 | extern void usb_seremu_flush_callback(void); 73 | extern volatile uint8_t usb_seremu_online; 74 | #endif 75 | 76 | #ifdef KEYBOARD_INTERFACE 77 | extern uint8_t keyboard_modifier_keys; 78 | extern uint8_t keyboard_keys[6]; 79 | extern uint8_t keyboard_protocol; 80 | extern uint8_t keyboard_idle_config; 81 | extern uint8_t keyboard_idle_count; 82 | extern volatile uint8_t keyboard_leds; 83 | #endif 84 | 85 | #ifdef MIDI_INTERFACE 86 | extern void usb_midi_flush_output(void); 87 | #endif 88 | 89 | #ifdef FLIGHTSIM_INTERFACE 90 | extern void usb_flightsim_flush_callback(void); 91 | #endif 92 | 93 | #ifdef AUDIO_INTERFACE 94 | extern uint16_t usb_audio_receive_buffer[]; 95 | extern uint16_t usb_audio_transmit_buffer[]; 96 | extern uint32_t usb_audio_sync_feedback; 97 | extern uint8_t usb_audio_receive_setting; 98 | extern uint8_t usb_audio_transmit_setting; 99 | extern void usb_audio_receive_callback(unsigned int len); 100 | extern unsigned int usb_audio_transmit_callback(void); 101 | extern int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen); 102 | extern int usb_audio_set_feature(void *stp, uint8_t *buf); 103 | #endif 104 | 105 | #ifdef MULTITOUCH_INTERFACE 106 | extern void usb_touchscreen_update_callback(void); 107 | #endif 108 | 109 | #ifdef XINPUT_INTERFACE 110 | extern void (*usb_xinput_recv_callback)(void); 111 | #endif 112 | 113 | 114 | #ifdef __cplusplus 115 | } 116 | #endif 117 | 118 | #ifdef CDC_DATA_INTERFACE 119 | #include "usb_serial.h" 120 | #endif 121 | 122 | #ifdef CDC2_DATA_INTERFACE 123 | #include "usb_serial2.h" 124 | #endif 125 | 126 | #ifdef CDC3_DATA_INTERFACE 127 | #include "usb_serial3.h" 128 | #endif 129 | 130 | #else // F_CPU < 20000000 131 | 132 | #ifdef __cplusplus 133 | extern "C" { 134 | #endif 135 | 136 | void usb_init(void); 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | 143 | #endif // F_CPU 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_inst.cpp: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include "usb_desc.h" 33 | 34 | #if F_CPU >= 20000000 35 | 36 | #ifdef CDC_DATA_INTERFACE 37 | #ifdef CDC_STATUS_INTERFACE 38 | usb_serial_class Serial; 39 | #endif 40 | #endif 41 | 42 | #ifdef CDC2_DATA_INTERFACE 43 | #ifdef CDC2_STATUS_INTERFACE 44 | usb_serial2_class SerialUSB1; 45 | #endif 46 | #endif 47 | 48 | #ifdef CDC3_DATA_INTERFACE 49 | #ifdef CDC3_STATUS_INTERFACE 50 | usb_serial3_class SerialUSB2; 51 | #endif 52 | #endif 53 | 54 | #ifdef MIDI_INTERFACE 55 | usb_midi_class usbMIDI; 56 | #endif 57 | 58 | #ifdef KEYBOARD_INTERFACE 59 | usb_keyboard_class Keyboard; 60 | #endif 61 | 62 | #ifdef MOUSE_INTERFACE 63 | usb_mouse_class Mouse; 64 | #endif 65 | 66 | #ifdef RAWHID_INTERFACE 67 | usb_rawhid_class RawHID; 68 | #endif 69 | 70 | #ifdef FLIGHTSIM_INTERFACE 71 | FlightSimClass FlightSim; 72 | #endif 73 | 74 | #ifdef SEREMU_INTERFACE 75 | usb_seremu_class Serial; 76 | #endif 77 | 78 | #ifdef JOYSTICK_INTERFACE 79 | usb_joystick_class Joystick; 80 | uint8_t usb_joystick_class::manual_mode = 0; 81 | #endif 82 | 83 | #ifdef USB_DISABLED 84 | usb_serial_class Serial; 85 | #endif 86 | 87 | #ifdef USB_XINPUT 88 | usb_serial_class Serial; 89 | #endif 90 | 91 | 92 | #else // F_CPU < 20 MHz 93 | 94 | #if defined(USB_SERIAL) || defined(USB_DUAL_SERIAL) || \ 95 | defined(USB_TRIPLE_SERIAL) || defined(USB_SERIAL_HID) 96 | usb_serial_class Serial; 97 | #elif (USB_DISABLED) 98 | usb_serial_class Serial; 99 | #else 100 | usb_seremu_class Serial; 101 | #endif 102 | 103 | #endif // F_CPU 104 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_serial.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #ifndef USBserial_h_ 32 | #define USBserial_h_ 33 | 34 | #include "usb_desc.h" 35 | 36 | #if (defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)) || defined(USB_DISABLED) || defined(USB_XINPUT) 37 | 38 | #include 39 | 40 | #if F_CPU >= 20000000 && !(defined(USB_DISABLED) || defined(USB_XINPUT)) 41 | 42 | #include "core_pins.h" // for millis() 43 | 44 | // C language implementation 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | int usb_serial_getchar(void); 49 | int usb_serial_peekchar(void); 50 | int usb_serial_available(void); 51 | int usb_serial_read(void *buffer, uint32_t size); 52 | void usb_serial_flush_input(void); 53 | int usb_serial_putchar(uint8_t c); 54 | int usb_serial_write(const void *buffer, uint32_t size); 55 | int usb_serial_write_buffer_free(void); 56 | void usb_serial_flush_output(void); 57 | void usb_serial_flush_callback(void); 58 | extern uint32_t usb_cdc_line_coding[2]; 59 | extern volatile uint32_t usb_cdc_line_rtsdtr_millis; 60 | extern volatile uint32_t systick_millis_count; 61 | extern volatile uint8_t usb_cdc_line_rtsdtr; 62 | extern volatile uint8_t usb_cdc_transmit_flush_timer; 63 | extern volatile uint8_t usb_configuration; 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #define USB_SERIAL_DTR 0x01 69 | #define USB_SERIAL_RTS 0x02 70 | 71 | // C++ interface 72 | #ifdef __cplusplus 73 | #include "Stream.h" 74 | class usb_serial_class : public Stream 75 | { 76 | public: 77 | constexpr usb_serial_class() {} 78 | void begin(long) { 79 | uint32_t millis_begin = systick_millis_count; 80 | while (!(*this)) { 81 | uint32_t elapsed = systick_millis_count - millis_begin; 82 | if (usb_configuration) { 83 | // Wait up to 2 seconds for Arduino Serial Monitor 84 | if (elapsed > 2000) break; 85 | } else { 86 | // But wait only 3/4 second if there is no sign the 87 | // USB host has begun the USB enumeration process. 88 | if (elapsed > 750) break; 89 | } 90 | yield(); 91 | } 92 | } 93 | void end() { /* TODO: flush output and shut down USB port */ }; 94 | virtual int available() { return usb_serial_available(); } 95 | virtual int read() { return usb_serial_getchar(); } 96 | virtual int peek() { return usb_serial_peekchar(); } 97 | virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB... 98 | virtual void clear(void) { usb_serial_flush_input(); } 99 | virtual size_t write(uint8_t c) { return usb_serial_putchar(c); } 100 | virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); } 101 | size_t write(unsigned long n) { return write((uint8_t)n); } 102 | size_t write(long n) { return write((uint8_t)n); } 103 | size_t write(unsigned int n) { return write((uint8_t)n); } 104 | size_t write(int n) { return write((uint8_t)n); } 105 | virtual int availableForWrite() { return usb_serial_write_buffer_free(); } 106 | using Print::write; 107 | void send_now(void) { usb_serial_flush_output(); } 108 | uint32_t baud(void) { return usb_cdc_line_coding[0]; } 109 | uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; } 110 | uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even 111 | uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; } 112 | uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } 113 | uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } 114 | operator bool() { 115 | yield(); 116 | return usb_configuration && (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) && 117 | ((uint32_t)(systick_millis_count - usb_cdc_line_rtsdtr_millis) >= 15); 118 | } 119 | size_t readBytes(char *buffer, size_t length) { 120 | size_t count=0; 121 | unsigned long startMillis = millis(); 122 | do { 123 | count += usb_serial_read(buffer + count, length - count); 124 | if (count >= length) return count; 125 | } while(millis() - startMillis < _timeout); 126 | setReadError(); 127 | return count; 128 | } 129 | 130 | }; 131 | extern usb_serial_class Serial; 132 | extern void serialEvent(void); 133 | #endif // __cplusplus 134 | 135 | 136 | #else // F_CPU < 20000000 137 | 138 | // Allow Arduino programs using Serial to compile, but Serial will do nothing. 139 | #ifdef __cplusplus 140 | #include "Stream.h" 141 | class usb_serial_class : public Stream 142 | { 143 | public: 144 | constexpr usb_serial_class() {} 145 | void begin(long) { }; 146 | void end() { }; 147 | virtual int available() { return 0; } 148 | virtual int read() { return -1; } 149 | virtual int peek() { return -1; } 150 | virtual void flush() { } 151 | virtual void clear() { } 152 | virtual size_t write(uint8_t c) { return 1; } 153 | virtual size_t write(const uint8_t *buffer, size_t size) { return size; } 154 | size_t write(unsigned long n) { return 1; } 155 | size_t write(long n) { return 1; } 156 | size_t write(unsigned int n) { return 1; } 157 | size_t write(int n) { return 1; } 158 | virtual int availableForWrite() { return 0; } 159 | using Print::write; 160 | void send_now(void) { } 161 | uint32_t baud(void) { return 0; } 162 | uint8_t stopbits(void) { return 1; } 163 | uint8_t paritytype(void) { return 0; } 164 | uint8_t numbits(void) { return 8; } 165 | uint8_t dtr(void) { return 1; } 166 | uint8_t rts(void) { return 1; } 167 | operator bool() { return true; } 168 | }; 169 | 170 | extern usb_serial_class Serial; 171 | extern void serialEvent(void); 172 | #endif // __cplusplus 173 | 174 | 175 | #endif // F_CPU 176 | 177 | #endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE 178 | 179 | #endif // USBserial_h_ 180 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_xinput.c: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016 Zachery Littell 4 | * Modified (c) 2019 David Madison 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "usb_dev.h" 26 | #include "usb_xinput.h" 27 | #include "core_pins.h" // for yield(), millis() 28 | #include // for memcpy() 29 | //#include "HardwareSerial.h" 30 | 31 | #ifdef XINPUT_INTERFACE // defined by usb_dev.h -> usb_desc.h 32 | #if F_CPU >= 20000000 33 | 34 | static const uint32_t timeout = 250; // ms 35 | 36 | void (*usb_xinput_recv_callback)(void) = NULL; 37 | 38 | // Function returns whether the microcontroller's USB 39 | // is configured or not (connected to driver) 40 | bool usb_xinput_connected(void) 41 | { 42 | return usb_configuration; 43 | } 44 | 45 | // Function to check if packets are available 46 | // to be received on the RX endpoint 47 | uint16_t usb_xinput_available(void) 48 | { 49 | uint16_t count; 50 | 51 | if (!usb_configuration) return 0; 52 | count = usb_rx_byte_count(XINPUT_RX_ENDPOINT); 53 | return count; 54 | } 55 | 56 | 57 | // Function receives packets from the RX endpoint 58 | int usb_xinput_recv(void *buffer, uint8_t nbytes) 59 | { 60 | usb_packet_t *rx_packet; 61 | uint32_t begin = millis(); 62 | 63 | while (1) { 64 | if (!usb_configuration) return -1; 65 | rx_packet = usb_rx(XINPUT_RX_ENDPOINT); 66 | if (rx_packet) break; 67 | if (millis() - begin > timeout || !timeout) return 0; 68 | yield(); 69 | } 70 | memcpy(buffer, rx_packet->buf, nbytes); 71 | usb_free(rx_packet); 72 | return nbytes; 73 | } 74 | 75 | // Maximum number of transmit packets to queue so we don't starve other endpoints for memory 76 | #define TX_PACKET_LIMIT 3 77 | 78 | // Function used to send packets out of the TX endpoint 79 | // This is used to send button reports 80 | int usb_xinput_send(const void *buffer, uint8_t nbytes) 81 | { 82 | usb_packet_t *tx_packet; 83 | uint32_t begin = millis(); 84 | 85 | while (1) { 86 | if (!usb_configuration) return -1; 87 | if (usb_tx_packet_count(XINPUT_TX_ENDPOINT) < TX_PACKET_LIMIT) { 88 | tx_packet = usb_malloc(); 89 | if (tx_packet) break; 90 | } 91 | if (millis() - begin > timeout) return 0; 92 | yield(); 93 | } 94 | memcpy(tx_packet->buf, buffer, nbytes); 95 | tx_packet->len = nbytes; 96 | usb_tx(XINPUT_TX_ENDPOINT, tx_packet); 97 | return nbytes; 98 | } 99 | 100 | #endif // F_CPU 101 | #endif // XINPUT_INTERFACE -------------------------------------------------------------------------------- /teensy/avr/cores/teensy3/usb_xinput.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016 Zachery Littell 4 | * Modified (c) 2019 David Madison 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef USBxinput_h_ 26 | #define USBxinput_h_ 27 | 28 | #include "usb_desc.h" 29 | 30 | #if defined(XINPUT_INTERFACE) 31 | 32 | #include 33 | #include 34 | 35 | // C language implementation 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | bool usb_xinput_connected(void); 40 | uint16_t usb_xinput_available(void); 41 | int usb_xinput_send(const void *buffer, uint8_t nbytes); 42 | int usb_xinput_recv(void *buffer, uint8_t nbytes); 43 | extern void (*usb_xinput_recv_callback)(void); 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | 49 | // C++ interface 50 | #ifdef __cplusplus 51 | class XInputUSB 52 | { 53 | public: 54 | static bool connected(void) { return usb_xinput_connected(); } 55 | static uint16_t available(void) { return usb_xinput_available(); } 56 | static int send(const void *buffer, uint8_t nbytes) { return usb_xinput_send(buffer, nbytes); } 57 | static int recv(void *buffer, uint8_t nbytes) { return usb_xinput_recv(buffer, nbytes); } 58 | static void setRecvCallback(void (*callback)(void)) { usb_xinput_recv_callback = callback; } 59 | }; 60 | 61 | #endif // __cplusplus 62 | 63 | #endif // XINPUT_INTERFACE 64 | 65 | #endif // USBxinput_h_ 66 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/WProgram.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #ifndef WProgram_h 32 | #define WProgram_h 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | // some libraries and sketches depend on this 40 | // AVR stuff, assuming Arduino.h or WProgram.h 41 | // automatically includes it... 42 | #include 43 | #include 44 | 45 | #include "avr_functions.h" 46 | #include "wiring.h" 47 | #include "HardwareSerial.h" 48 | 49 | #ifdef __cplusplus 50 | 51 | #include "inplace_function.h" 52 | #include "avr_emulation.h" 53 | #include "usb_serial.h" 54 | #include "usb_seremu.h" 55 | #include "usb_keyboard.h" 56 | #include "usb_mouse.h" 57 | #include "usb_joystick.h" 58 | #include "usb_midi.h" 59 | #include "usb_rawhid.h" 60 | #include "usb_flightsim.h" 61 | //#include "usb_mtp.h" 62 | #include "usb_audio.h" 63 | #include "usb_touch.h" 64 | //#include "usb_undef.h" // do not allow usb_desc.h stuff to leak to user programs 65 | #include "usb_xinput.h" 66 | 67 | #include "WCharacter.h" 68 | #include "WString.h" 69 | #include "elapsedMillis.h" 70 | #include "IntervalTimer.h" 71 | #include "CrashReport.h" 72 | 73 | uint16_t makeWord(uint16_t w); 74 | uint16_t makeWord(byte h, byte l); 75 | 76 | #define word(...) makeWord(__VA_ARGS__) 77 | 78 | // Measure the duration of a pulse at a digital pin. The state may be 79 | // either HIGH or LOW, to measure a pulse remains either high or low. Return 80 | // is pulse duration in microseconds, or zero if no pulse was detected. 81 | unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); 82 | static unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L) __attribute__((unused)); 83 | // Measure the duration of a pulse at a digital pin. The state may be 84 | // either HIGH or LOW, to measure a pulse remains either high or low. Return 85 | // is pulse duration in microseconds, or zero if no pulse was detected. 86 | static unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) { 87 | return pulseIn(pin, state, timeout); 88 | } 89 | 90 | // Creates a square wave output on a digital pin at a specific frequency. If 91 | // duration is specified (in milliseconds), the waveform will automatically 92 | // stop. Otherwise, it continues into noTone() or another tone() call uses a 93 | // different pin. Only 1 waveform at a time is supported. This waveform works 94 | // on any digitial pin, but uses interrupts to create the output. For more 95 | // efficient output, use PWM pins with analogWriteFrequency(). 96 | void tone(uint8_t pin, uint16_t frequency, uint32_t duration = 0); 97 | // Ends a square wave output created by a prior called to tone(). 98 | void noTone(uint8_t pin); 99 | 100 | // WMath prototypes 101 | 102 | // Returns a pseudo-random number as a 32 bit signed integer. See randomSeed() 103 | // for info about pseudo-random properties. 104 | int32_t random(void); 105 | // Returns a pseudo-random number less "howbig". For example, random(100) 106 | // will return numbers beteen 0 to 99. See randomSeed() for info about 107 | // pseudo-random properties. 108 | uint32_t random(uint32_t howbig); 109 | // Returns a pseudo-random within a range. For example, random(50, 100) 110 | // will return numbers beteen 50 to 99. See randomSeed() for info about 111 | // pseudo-random properties. 112 | int32_t random(int32_t howsmall, int32_t howbig); 113 | // Initialize the pseudo-random number generator. Pseudo-random numbers 114 | // follow a sequence, but the sequence is so long that initializing at an 115 | // unpredictable starting point gives effectively random numbers useful 116 | // for most non-cryptographic uses. The Entropy library is recommended 117 | // to produce a truly random number for randomSeed(). You could just use 118 | // Entropy for all random numbers, but the speed is much slower than 119 | // generating pseudo-random numbers. 120 | void randomSeed(uint32_t newseed); 121 | void srandom(unsigned int newseed); 122 | 123 | #include "pins_arduino.h" 124 | 125 | #endif // __cplusplus 126 | 127 | 128 | // Fast memcpy 129 | #ifdef __cplusplus 130 | extern "C" { 131 | extern void *memcpy (void *dst, const void *src, size_t count); 132 | } 133 | #else 134 | extern void *memcpy (void *dst, const void *src, size_t count); 135 | #endif 136 | 137 | 138 | #endif // WProgram_h 139 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/usb.c: -------------------------------------------------------------------------------- 1 | #include "usb_dev.h" 2 | #define USB_DESC_LIST_DEFINE 3 | #include "usb_desc.h" 4 | #include "usb_serial.h" 5 | #include "usb_seremu.h" 6 | #include "usb_rawhid.h" 7 | #include "usb_keyboard.h" 8 | #include "usb_mouse.h" 9 | #include "usb_joystick.h" 10 | #include "usb_flightsim.h" 11 | #include "usb_touch.h" 12 | #include "usb_midi.h" 13 | #include "usb_audio.h" 14 | #include "usb_mtp.h" 15 | #include "usb_xinput.h" 16 | #include "core_pins.h" // for delay() 17 | #include "avr/pgmspace.h" 18 | #include 19 | #include "debug/printf.h" 20 | 21 | //#define LOG_SIZE 20 22 | //uint32_t transfer_log_head=0; 23 | //uint32_t transfer_log_count=0; 24 | //uint32_t transfer_log[LOG_SIZE]; 25 | 26 | // device mode, page 3155 27 | 28 | #if defined(NUM_ENDPOINTS) 29 | 30 | typedef struct endpoint_struct endpoint_t; 31 | 32 | struct endpoint_struct { 33 | uint32_t config; 34 | uint32_t current; 35 | uint32_t next; 36 | uint32_t status; 37 | uint32_t pointer0; 38 | uint32_t pointer1; 39 | uint32_t pointer2; 40 | uint32_t pointer3; 41 | uint32_t pointer4; 42 | uint32_t reserved; 43 | uint32_t setup0; 44 | uint32_t setup1; 45 | transfer_t *first_transfer; 46 | transfer_t *last_transfer; 47 | void (*callback_function)(transfer_t *completed_transfer); 48 | uint32_t unused1; 49 | }; 50 | 51 | /*struct transfer_struct { 52 | uint32_t next; 53 | uint32_t status; 54 | uint32_t pointer0; 55 | uint32_t pointer1; 56 | uint32_t pointer2; 57 | uint32_t pointer3; 58 | uint32_t pointer4; 59 | uint32_t callback_param; 60 | };*/ 61 | 62 | endpoint_t endpoint_queue_head[(NUM_ENDPOINTS+1)*2] __attribute__ ((used, aligned(4096), section(".endpoint_queue") )); 63 | 64 | transfer_t endpoint0_transfer_data __attribute__ ((used, aligned(32))); 65 | transfer_t endpoint0_transfer_ack __attribute__ ((used, aligned(32))); 66 | 67 | 68 | typedef union { 69 | struct { 70 | union { 71 | struct { 72 | uint8_t bmRequestType; 73 | uint8_t bRequest; 74 | }; 75 | uint16_t wRequestAndType; 76 | }; 77 | uint16_t wValue; 78 | uint16_t wIndex; 79 | uint16_t wLength; 80 | }; 81 | struct { 82 | uint32_t word1; 83 | uint32_t word2; 84 | }; 85 | uint64_t bothwords; 86 | } setup_t; 87 | 88 | static setup_t endpoint0_setupdata; 89 | static uint32_t endpoint0_notify_mask=0; 90 | static uint32_t endpointN_notify_mask=0; 91 | //static int reset_count=0; 92 | volatile uint8_t usb_configuration = 0; // non-zero when USB host as configured device 93 | volatile uint8_t usb_high_speed = 0; // non-zero if running at 480 Mbit/sec speed 94 | static uint8_t endpoint0_buffer[8]; 95 | static uint8_t sof_usage = 0; 96 | static uint8_t usb_reboot_timer = 0; 97 | 98 | extern uint8_t usb_descriptor_buffer[]; // defined in usb_desc.c 99 | extern const uint8_t usb_config_descriptor_480[]; 100 | extern const uint8_t usb_config_descriptor_12[]; 101 | 102 | void (*usb_timer0_callback)(void) = NULL; 103 | void (*usb_timer1_callback)(void) = NULL; 104 | 105 | void usb_isr(void); 106 | static void endpoint0_setup(uint64_t setupdata); 107 | static void endpoint0_transmit(const void *data, uint32_t len, int notify); 108 | static void endpoint0_receive(void *data, uint32_t len, int notify); 109 | static void endpoint0_complete(void); 110 | 111 | 112 | static void run_callbacks(endpoint_t *ep); 113 | 114 | 115 | FLASHMEM void usb_init(void) 116 | { 117 | // TODO: only enable when VBUS detected 118 | // TODO: return to low power mode when VBUS removed 119 | // TODO: protect PMU access with MPU 120 | PMU_REG_3P0 = PMU_REG_3P0_OUTPUT_TRG(0x0F) | PMU_REG_3P0_BO_OFFSET(6) 121 | | PMU_REG_3P0_ENABLE_LINREG; 122 | 123 | usb_init_serialnumber(); 124 | 125 | // assume PLL3 is already running - already done by usb_pll_start() in main.c 126 | 127 | CCM_CCGR6 |= CCM_CCGR6_USBOH3(CCM_CCGR_ON); // turn on clocks to USB peripheral 128 | 129 | printf("BURSTSIZE=%08lX\n", USB1_BURSTSIZE); 130 | //USB1_BURSTSIZE = USB_BURSTSIZE_TXPBURST(4) | USB_BURSTSIZE_RXPBURST(4); 131 | USB1_BURSTSIZE = 0x0404; 132 | printf("BURSTSIZE=%08lX\n", USB1_BURSTSIZE); 133 | printf("USB1_TXFILLTUNING=%08lX\n", USB1_TXFILLTUNING); 134 | 135 | // Before programming this register, the PHY clocks must be enabled in registers 136 | // USBPHYx_CTRLn and CCM_ANALOG_USBPHYx_PLL_480_CTRLn. 137 | 138 | //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD); 139 | //printf("USBPHY1_TX=%08lX\n", USBPHY1_TX); 140 | //printf("USBPHY1_RX=%08lX\n", USBPHY1_RX); 141 | //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL); 142 | //printf("USB1_USBMODE=%08lX\n", USB1_USBMODE); 143 | 144 | // turn on PLL3, wait for 480 MHz lock? 145 | // turn on CCM clock gates? CCGR6[CG0] 146 | #if 1 147 | if ((USBPHY1_PWD & (USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | USBPHY_PWD_RXPWD1PT1 148 | | USBPHY_PWD_RXPWDENV | USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS 149 | | USBPHY_PWD_TXPWDFS)) || (USB1_USBMODE & USB_USBMODE_CM_MASK)) { 150 | // USB controller is turned on from previous use 151 | // reset needed to turn it off & start from clean slate 152 | USBPHY1_CTRL_SET = USBPHY_CTRL_SFTRST; // USBPHY1_CTRL page 3292 153 | USB1_USBCMD |= USB_USBCMD_RST; // reset controller 154 | int count=0; 155 | while (USB1_USBCMD & USB_USBCMD_RST) count++; 156 | NVIC_CLEAR_PENDING(IRQ_USB1); 157 | USBPHY1_CTRL_CLR = USBPHY_CTRL_SFTRST; // reset PHY 158 | //USB1_USBSTS = USB1_USBSTS; // TODO: is this needed? 159 | printf("USB reset took %d loops\n", count); 160 | //delay(10); 161 | //printf("\n"); 162 | //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD); 163 | //printf("USBPHY1_TX=%08lX\n", USBPHY1_TX); 164 | //printf("USBPHY1_RX=%08lX\n", USBPHY1_RX); 165 | //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL); 166 | //printf("USB1_USBMODE=%08lX\n", USB1_USBMODE); 167 | delay(25); 168 | } 169 | #endif 170 | // Device Controller Initialization, page 2351 (Rev 2, 12/2019) 171 | // USBCMD pg 3216 172 | // USBSTS pg 3220 173 | // USBINTR pg 3224 174 | // DEVICEADDR pg 3227 175 | // ENDPTLISTADDR 3229 176 | // USBMODE pg 3244 177 | // ENDPTSETUPSTAT 3245 178 | // ENDPTPRIME pg 3246 179 | // ENDPTFLUSH pg 3247 180 | // ENDPTSTAT pg 3247 181 | // ENDPTCOMPLETE 3248 182 | // ENDPTCTRL0 pg 3249 183 | 184 | USBPHY1_CTRL_CLR = USBPHY_CTRL_CLKGATE; 185 | USBPHY1_PWD = 0; 186 | //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD); 187 | //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL); 188 | 189 | USB1_USBMODE = USB_USBMODE_CM(2) | USB_USBMODE_SLOM; 190 | memset(endpoint_queue_head, 0, sizeof(endpoint_queue_head)); 191 | endpoint_queue_head[0].config = (64 << 16) | (1 << 15); 192 | endpoint_queue_head[1].config = (64 << 16); 193 | USB1_ENDPOINTLISTADDR = (uint32_t)&endpoint_queue_head; 194 | // Recommended: enable all device interrupts including: USBINT, USBERRINT, 195 | // Port Change Detect, USB Reset Received, DCSuspend. 196 | USB1_USBINTR = USB_USBINTR_UE | USB_USBINTR_UEE | /* USB_USBINTR_PCE | */ 197 | USB_USBINTR_URE | USB_USBINTR_SLE; 198 | //_VectorsRam[IRQ_USB1+16] = &usb_isr; 199 | attachInterruptVector(IRQ_USB1, &usb_isr); 200 | NVIC_ENABLE_IRQ(IRQ_USB1); 201 | //printf("USB1_ENDPTCTRL0=%08lX\n", USB1_ENDPTCTRL0); 202 | //printf("USB1_ENDPTCTRL1=%08lX\n", USB1_ENDPTCTRL1); 203 | //printf("USB1_ENDPTCTRL2=%08lX\n", USB1_ENDPTCTRL2); 204 | //printf("USB1_ENDPTCTRL3=%08lX\n", USB1_ENDPTCTRL3); 205 | USB1_USBCMD = USB_USBCMD_RS; 206 | //transfer_log_head = 0; 207 | //transfer_log_count = 0; 208 | //USB1_PORTSC1 |= USB_PORTSC1_PFSC; // force 12 Mbit/sec 209 | } 210 | 211 | 212 | FLASHMEM __attribute__((noinline)) void _reboot_Teensyduino_(void) 213 | { 214 | if (!(HW_OCOTP_CFG5 & 0x02)) { 215 | asm("bkpt #251"); // run bootloader 216 | } else { 217 | __disable_irq(); // secure mode NXP ROM reboot 218 | USB1_USBCMD = 0; 219 | IOMUXC_GPR_GPR16 = 0x00200003; 220 | // TODO: wipe all RAM for security 221 | __asm__ volatile("mov sp, %0" : : "r" (0x20201000) : ); 222 | __asm__ volatile("dsb":::"memory"); 223 | volatile uint32_t * const p = (uint32_t *)0x20208000; 224 | *p = 0xEB120000; 225 | ((void (*)(volatile void *))(*(uint32_t *)(*(uint32_t *)0x0020001C + 8)))(p); 226 | } 227 | __builtin_unreachable(); 228 | } 229 | 230 | 231 | void usb_isr(void) 232 | { 233 | //printf("*"); 234 | 235 | // Port control in device mode is only used for 236 | // status port reset, suspend, and current connect status. 237 | uint32_t status = USB1_USBSTS; 238 | USB1_USBSTS = status; 239 | 240 | // USB_USBSTS_SLI - set to 1 when enters a suspend state from an active state 241 | // USB_USBSTS_SRI - set at start of frame 242 | // USB_USBSTS_SRI - set when USB reset detected 243 | 244 | if (status & USB_USBSTS_UI) { 245 | //printf("data\n"); 246 | uint32_t setupstatus = USB1_ENDPTSETUPSTAT; 247 | //printf("USB1_ENDPTSETUPSTAT=%X\n", setupstatus); 248 | while (setupstatus) { 249 | USB1_ENDPTSETUPSTAT = setupstatus; 250 | setup_t s; 251 | do { 252 | USB1_USBCMD |= USB_USBCMD_SUTW; 253 | s.word1 = endpoint_queue_head[0].setup0; 254 | s.word2 = endpoint_queue_head[0].setup1; 255 | } while (!(USB1_USBCMD & USB_USBCMD_SUTW)); 256 | USB1_USBCMD &= ~USB_USBCMD_SUTW; 257 | //printf("setup %08lX %08lX\n", s.word1, s.word2); 258 | USB1_ENDPTFLUSH = (1<<16) | (1<<0); // page 3174 259 | while (USB1_ENDPTFLUSH & ((1<<16) | (1<<0))) ; 260 | endpoint0_notify_mask = 0; 261 | endpoint0_setup(s.bothwords); 262 | setupstatus = USB1_ENDPTSETUPSTAT; // page 3175 263 | } 264 | uint32_t completestatus = USB1_ENDPTCOMPLETE; 265 | if (completestatus) { 266 | USB1_ENDPTCOMPLETE = completestatus; 267 | //printf("USB1_ENDPTCOMPLETE=%lX\n", completestatus); 268 | if (completestatus & endpoint0_notify_mask) { 269 | endpoint0_notify_mask = 0; 270 | endpoint0_complete(); 271 | } 272 | completestatus &= endpointN_notify_mask; 273 | #if 1 274 | if (completestatus) { 275 | 276 | // transmit: 277 | uint32_t tx = completestatus >> 16; 278 | while (tx) { 279 | int p=__builtin_ctz(tx); 280 | run_callbacks(endpoint_queue_head + p * 2 + 1); 281 | tx &= ~(1<= 3) { 326 | // shut off USB - easier to see results in protocol analyzer 327 | //USB1_USBCMD &= ~USB_USBCMD_RS; 328 | //printf("shut off USB\n"); 329 | //} 330 | } 331 | if (status & USB_USBSTS_TI0) { 332 | if (usb_timer0_callback != NULL) usb_timer0_callback(); 333 | } 334 | if (status & USB_USBSTS_TI1) { 335 | if (usb_timer1_callback != NULL) usb_timer1_callback(); 336 | } 337 | if (status & USB_USBSTS_PCI) { 338 | if (USB1_PORTSC1 & USB_PORTSC1_HSP) { 339 | //printf("port at 480 Mbit\n"); 340 | usb_high_speed = 1; 341 | } else { 342 | //printf("port at 12 Mbit\n"); 343 | usb_high_speed = 0; 344 | } 345 | } 346 | if (status & USB_USBSTS_SLI) { // page 3165 347 | //printf("suspend\n"); 348 | } 349 | if (status & USB_USBSTS_UEI) { 350 | //printf("error\n"); 351 | } 352 | if ((USB1_USBINTR & USB_USBINTR_SRE) && (status & USB_USBSTS_SRI)) { 353 | //printf("sof %d\n", usb_reboot_timer); 354 | if (usb_reboot_timer) { 355 | if (--usb_reboot_timer == 0) { 356 | usb_stop_sof_interrupts(NUM_INTERFACE); 357 | _reboot_Teensyduino_(); 358 | } 359 | } 360 | #ifdef MIDI_INTERFACE 361 | usb_midi_flush_output(); 362 | #endif 363 | #ifdef MULTITOUCH_INTERFACE 364 | usb_touchscreen_update_callback(); 365 | #endif 366 | #ifdef FLIGHTSIM_INTERFACE 367 | usb_flightsim_flush_output(); 368 | #endif 369 | } 370 | } 371 | 372 | 373 | void usb_start_sof_interrupts(int interface) 374 | { 375 | __disable_irq(); 376 | sof_usage |= (1 << interface); 377 | uint32_t intr = USB1_USBINTR; 378 | if (!(intr & USB_USBINTR_SRE)) { 379 | USB1_USBSTS = USB_USBSTS_SRI; // clear prior SOF before SOF IRQ enable 380 | USB1_USBINTR = intr | USB_USBINTR_SRE; 381 | } 382 | __enable_irq(); 383 | } 384 | 385 | void usb_stop_sof_interrupts(int interface) 386 | { 387 | sof_usage &= ~(1 << interface); 388 | if (sof_usage == 0) { 389 | USB1_USBINTR &= ~USB_USBINTR_SRE; 390 | } 391 | } 392 | 393 | 394 | 395 | 396 | /* 397 | struct transfer_struct { // table 55-60, pg 3159 398 | uint32_t next; 399 | uint32_t status; 400 | uint32_t pointer0; 401 | uint32_t pointer1; 402 | uint32_t pointer2; 403 | uint32_t pointer3; 404 | uint32_t pointer4; 405 | uint32_t unused1; 406 | }; 407 | transfer_t endpoint0_transfer_data __attribute__ ((aligned(32)));; 408 | transfer_t endpoint0_transfer_ack __attribute__ ((aligned(32)));; 409 | */ 410 | 411 | static uint8_t reply_buffer[8]; 412 | 413 | static void endpoint0_setup(uint64_t setupdata) 414 | { 415 | setup_t setup; 416 | uint32_t endpoint, dir, ctrl; 417 | const usb_descriptor_list_t *list; 418 | 419 | setup.bothwords = setupdata; 420 | switch (setup.wRequestAndType) { 421 | case 0x0500: // SET_ADDRESS 422 | endpoint0_receive(NULL, 0, 0); 423 | USB1_DEVICEADDR = USB_DEVICEADDR_USBADR(setup.wValue) | USB_DEVICEADDR_USBADRA; 424 | return; 425 | case 0x0900: // SET_CONFIGURATION 426 | usb_configuration = setup.wValue; 427 | // configure all other endpoints 428 | #if defined(ENDPOINT1_CONFIG) 429 | USB1_ENDPTCTRL1 = ENDPOINT1_CONFIG; // added for XInput TX 430 | #endif 431 | #if defined(ENDPOINT2_CONFIG) 432 | USB1_ENDPTCTRL2 = ENDPOINT2_CONFIG; 433 | #endif 434 | #if defined(ENDPOINT3_CONFIG) 435 | USB1_ENDPTCTRL3 = ENDPOINT3_CONFIG; 436 | #endif 437 | #if defined(ENDPOINT4_CONFIG) 438 | USB1_ENDPTCTRL4 = ENDPOINT4_CONFIG; 439 | #endif 440 | #if defined(ENDPOINT5_CONFIG) 441 | USB1_ENDPTCTRL5 = ENDPOINT5_CONFIG; 442 | #endif 443 | #if defined(ENDPOINT6_CONFIG) 444 | USB1_ENDPTCTRL6 = ENDPOINT6_CONFIG; 445 | #endif 446 | #if defined(ENDPOINT7_CONFIG) 447 | USB1_ENDPTCTRL7 = ENDPOINT7_CONFIG; 448 | #endif 449 | #if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE) 450 | usb_serial_configure(); 451 | #elif defined(SEREMU_INTERFACE) 452 | usb_seremu_configure(); 453 | #endif 454 | #if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE) 455 | usb_serial2_configure(); 456 | #endif 457 | #if defined(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE) 458 | usb_serial3_configure(); 459 | #endif 460 | #if defined(RAWHID_INTERFACE) 461 | usb_rawhid_configure(); 462 | #endif 463 | #if defined(KEYBOARD_INTERFACE) 464 | usb_keyboard_configure(); 465 | #endif 466 | #if defined(MOUSE_INTERFACE) 467 | usb_mouse_configure(); 468 | #endif 469 | #if defined(FLIGHTSIM_INTERFACE) 470 | usb_flightsim_configure(); 471 | #endif 472 | #if defined(JOYSTICK_INTERFACE) 473 | usb_joystick_configure(); 474 | #endif 475 | #if defined(MULTITOUCH_INTERFACE) 476 | usb_touchscreen_configure(); 477 | #endif 478 | #if defined(MIDI_INTERFACE) 479 | usb_midi_configure(); 480 | #endif 481 | #if defined(AUDIO_INTERFACE) 482 | usb_audio_configure(); 483 | #endif 484 | #if defined(MTP_INTERFACE) 485 | usb_mtp_configure(); 486 | #endif 487 | #if defined(EXPERIMENTAL_INTERFACE) 488 | memset(endpoint_queue_head + 2, 0, sizeof(endpoint_t) * 2); 489 | endpoint_queue_head[2].pointer4 = 0xB8C6CF5D; 490 | endpoint_queue_head[3].pointer4 = 0x74D59319; 491 | #endif 492 | #if defined(XINPUT_INTERFACE) 493 | usb_xinput_configure(); 494 | #endif 495 | endpoint0_receive(NULL, 0, 0); 496 | return; 497 | case 0x0880: // GET_CONFIGURATION 498 | reply_buffer[0] = usb_configuration; 499 | endpoint0_transmit(reply_buffer, 1, 0); 500 | return; 501 | case 0x0080: // GET_STATUS (device) 502 | reply_buffer[0] = 0; 503 | reply_buffer[1] = 0; 504 | endpoint0_transmit(reply_buffer, 2, 0); 505 | return; 506 | case 0x0082: // GET_STATUS (endpoint) 507 | endpoint = setup.wIndex & 0x7F; 508 | if (endpoint > 7) break; 509 | dir = setup.wIndex & 0x80; 510 | ctrl = *((uint32_t *)&USB1_ENDPTCTRL0 + endpoint); 511 | reply_buffer[0] = 0; 512 | reply_buffer[1] = 0; 513 | if ((dir && (ctrl & USB_ENDPTCTRL_TXS)) || (!dir && (ctrl & USB_ENDPTCTRL_RXS))) { 514 | reply_buffer[0] = 1; 515 | } 516 | endpoint0_transmit(reply_buffer, 2, 0); 517 | return; 518 | case 0x0302: // SET_FEATURE (endpoint) 519 | endpoint = setup.wIndex & 0x7F; 520 | if (endpoint > 7) break; 521 | dir = setup.wIndex & 0x80; 522 | if (dir) { 523 | *((volatile uint32_t *)&USB1_ENDPTCTRL0 + endpoint) |= USB_ENDPTCTRL_TXS; 524 | } else { 525 | *((volatile uint32_t *)&USB1_ENDPTCTRL0 + endpoint) |= USB_ENDPTCTRL_RXS; 526 | } 527 | endpoint0_receive(NULL, 0, 0); 528 | return; 529 | case 0x0102: // CLEAR_FEATURE (endpoint) 530 | endpoint = setup.wIndex & 0x7F; 531 | if (endpoint > 7) break; 532 | dir = setup.wIndex & 0x80; 533 | if (dir) { 534 | *((volatile uint32_t *)&USB1_ENDPTCTRL0 + endpoint) &= ~USB_ENDPTCTRL_TXS; 535 | } else { 536 | *((volatile uint32_t *)&USB1_ENDPTCTRL0 + endpoint) &= ~USB_ENDPTCTRL_RXS; 537 | } 538 | endpoint0_receive(NULL, 0, 0); 539 | return; 540 | #ifdef EXPERIMENTAL_INTERFACE 541 | case 0xF8C0: // GET_MS_DESCRIPTOR (bRequest=0xF8 because microsoft_os_string_desc) 542 | if ((setup.wIndex & 0xFF00) != 0) break; // 1=Genre, 4=Compat ID, 5=Properties 543 | setup.wIndex |= 0xEE00; // alter wIndex and treat as normal USB descriptor 544 | __attribute__((fallthrough)); 545 | #endif 546 | case 0x0680: // GET_DESCRIPTOR 547 | case 0x0681: 548 | for (list = usb_descriptor_list; list->addr != NULL; list++) { 549 | if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) { 550 | uint32_t datalen; 551 | if ((setup.wValue >> 8) == 3) { 552 | // for string descriptors, use the descriptor's 553 | // length field, allowing runtime configured length. 554 | datalen = *(list->addr); 555 | } else { 556 | datalen = list->length; 557 | } 558 | if (datalen > setup.wLength) datalen = setup.wLength; 559 | 560 | // copy the descriptor, from PROGMEM to DMAMEM 561 | if (setup.wValue == 0x200) { 562 | // config descriptor needs to adapt to speed 563 | const uint8_t *src = usb_config_descriptor_12; 564 | if (usb_high_speed) src = usb_config_descriptor_480; 565 | memcpy(usb_descriptor_buffer, src, datalen); 566 | } else if (setup.wValue == 0x700) { 567 | // other speed config also needs to adapt 568 | const uint8_t *src = usb_config_descriptor_480; 569 | if (usb_high_speed) src = usb_config_descriptor_12; 570 | memcpy(usb_descriptor_buffer, src, datalen); 571 | usb_descriptor_buffer[1] = 7; 572 | } else { 573 | memcpy(usb_descriptor_buffer, list->addr, datalen); 574 | } 575 | // prep transmit 576 | arm_dcache_flush_delete(usb_descriptor_buffer, datalen); 577 | endpoint0_transmit(usb_descriptor_buffer, datalen, 0); 578 | return; 579 | } 580 | } 581 | break; 582 | #if defined(CDC_STATUS_INTERFACE) 583 | case 0x2221: // CDC_SET_CONTROL_LINE_STATE 584 | #ifdef CDC_STATUS_INTERFACE 585 | if (setup.wIndex == CDC_STATUS_INTERFACE) { 586 | usb_cdc_line_rtsdtr_millis = systick_millis_count; 587 | usb_cdc_line_rtsdtr = setup.wValue; 588 | } 589 | #endif 590 | #ifdef CDC2_STATUS_INTERFACE 591 | if (setup.wIndex == CDC2_STATUS_INTERFACE) { 592 | usb_cdc2_line_rtsdtr_millis = systick_millis_count; 593 | usb_cdc2_line_rtsdtr = setup.wValue; 594 | } 595 | #endif 596 | #ifdef CDC3_STATUS_INTERFACE 597 | if (setup.wIndex == CDC3_STATUS_INTERFACE) { 598 | usb_cdc3_line_rtsdtr_millis = systick_millis_count; 599 | usb_cdc3_line_rtsdtr = setup.wValue; 600 | } 601 | #endif 602 | __attribute__((fallthrough)); 603 | // fall through to next case, to always send ZLP ACK 604 | case 0x2321: // CDC_SEND_BREAK 605 | endpoint0_receive(NULL, 0, 0); 606 | return; 607 | case 0x2021: // CDC_SET_LINE_CODING 608 | if (setup.wLength != 7) break; 609 | endpoint0_setupdata.bothwords = setupdata; 610 | endpoint0_receive(endpoint0_buffer, 7, 1); 611 | return; 612 | #endif 613 | #if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE) 614 | case 0x0921: // HID SET_REPORT 615 | if (setup.wLength <= sizeof(endpoint0_buffer)) { 616 | //printf("hid set report %x %x\n", setup.word1, setup.word2); 617 | endpoint0_setupdata.bothwords = setup.bothwords; 618 | endpoint0_buffer[0] = 0xE9; 619 | endpoint0_receive(endpoint0_buffer, setup.wLength, 1); 620 | return; 621 | } 622 | break; 623 | #endif 624 | #if defined(AUDIO_INTERFACE) 625 | case 0x0B01: // SET_INTERFACE (alternate setting) 626 | if (setup.wIndex == AUDIO_INTERFACE+1) { 627 | usb_audio_transmit_setting = setup.wValue; 628 | if (usb_audio_transmit_setting > 0) { 629 | // TODO: set up AUDIO_TX_ENDPOINT to transmit 630 | } 631 | endpoint0_receive(NULL, 0, 0); 632 | return; 633 | } else if (setup.wIndex == AUDIO_INTERFACE+2) { 634 | usb_audio_receive_setting = setup.wValue; 635 | endpoint0_receive(NULL, 0, 0); 636 | return; 637 | } 638 | break; 639 | case 0x0A81: // GET_INTERFACE (alternate setting) 640 | if (setup.wIndex == AUDIO_INTERFACE+1) { 641 | endpoint0_buffer[0] = usb_audio_transmit_setting; 642 | endpoint0_transmit(endpoint0_buffer, 1, 0); 643 | return; 644 | } else if (setup.wIndex == AUDIO_INTERFACE+2) { 645 | endpoint0_buffer[0] = usb_audio_receive_setting; 646 | endpoint0_transmit(endpoint0_buffer, 1, 0); 647 | return; 648 | } 649 | break; 650 | case 0x0121: // SET FEATURE 651 | case 0x0221: 652 | case 0x0321: 653 | case 0x0421: 654 | //printf("set_feature, word1=%x, len=%d\n", setup.word1, setup.wLength); 655 | if (setup.wLength <= sizeof(endpoint0_buffer)) { 656 | endpoint0_setupdata.bothwords = setupdata; 657 | endpoint0_receive(endpoint0_buffer, setup.wLength, 1); 658 | return; // handle these after ACK 659 | } 660 | break; 661 | case 0x81A1: // GET FEATURE 662 | case 0x82A1: 663 | case 0x83A1: 664 | case 0x84A1: 665 | if (setup.wLength <= sizeof(endpoint0_buffer)) { 666 | uint32_t len; 667 | if (usb_audio_get_feature(&setup, endpoint0_buffer, &len)) { 668 | //printf("GET feature, len=%d\n", len); 669 | endpoint0_transmit(endpoint0_buffer, len, 0); 670 | return; 671 | } 672 | } 673 | break; 674 | case 0x81A2: // GET_CUR (wValue=0, wIndex=interface, wLength=len) 675 | if (setup.wLength >= 3) { 676 | endpoint0_buffer[0] = 44100 & 255; 677 | endpoint0_buffer[1] = 44100 >> 8; 678 | endpoint0_buffer[2] = 0; 679 | endpoint0_transmit(endpoint0_buffer, 3, 0); 680 | return; 681 | } 682 | break; 683 | #endif 684 | #if defined(MULTITOUCH_INTERFACE) 685 | case 0x01A1: 686 | if (setup.wValue == 0x0300 && setup.wIndex == MULTITOUCH_INTERFACE) { 687 | endpoint0_buffer[0] = MULTITOUCH_FINGERS; 688 | endpoint0_transmit(endpoint0_buffer, 1, 0); 689 | return; 690 | } else if (setup.wValue == 0x0100 && setup.wIndex == MULTITOUCH_INTERFACE) { 691 | memset(endpoint0_buffer, 0, 8); 692 | endpoint0_transmit(endpoint0_buffer, 8, 0); 693 | return; 694 | } 695 | break; 696 | #endif 697 | #if defined(MTP_INTERFACE) 698 | case 0x6421: // Cancel Request, Still Image Class 1.0, 5.2.1, page 8 699 | if (setup.wLength == 6) { 700 | endpoint0_setupdata.bothwords = setupdata; 701 | endpoint0_receive(endpoint0_buffer, setup.wLength, 1); 702 | return; 703 | } 704 | break; 705 | case 0x65A1: // Get Extended Event Data, Still Image Class 1.0, 5.2.2, page 9 706 | break; 707 | case 0x6621: // Device Reset, Still Image Class 1.0, 5.2.3 page 10 708 | break; 709 | case 0x67A1: // Get Device Status, Still Image Class 1.0, 5.2.4, page 10 710 | if (setup.wLength >= 4) { 711 | endpoint0_buffer[0] = 4; 712 | endpoint0_buffer[1] = 0; 713 | endpoint0_buffer[2] = usb_mtp_status; 714 | endpoint0_buffer[3] = 0x20; 715 | endpoint0_transmit(endpoint0_buffer, 4, 0); 716 | //if (usb_mtp_status == 0x19) usb_mtp_status = 0x01; // testing only 717 | return; 718 | } 719 | break; 720 | #endif 721 | } 722 | printf("endpoint 0 stall\n"); 723 | USB1_ENDPTCTRL0 = 0x000010001; // stall 724 | } 725 | 726 | static void endpoint0_transmit(const void *data, uint32_t len, int notify) 727 | { 728 | //printf("tx %lu\n", len); 729 | if (len > 0) { 730 | // Executing A Transfer Descriptor, page 3182 731 | endpoint0_transfer_data.next = 1; 732 | endpoint0_transfer_data.status = (len << 16) | (1<<7); 733 | uint32_t addr = (uint32_t)data; 734 | endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159 735 | endpoint0_transfer_data.pointer1 = addr + 4096; 736 | endpoint0_transfer_data.pointer2 = addr + 8192; 737 | endpoint0_transfer_data.pointer3 = addr + 12288; 738 | endpoint0_transfer_data.pointer4 = addr + 16384; 739 | // Case 1: Link list is empty, page 3182 740 | endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_data; 741 | endpoint_queue_head[1].status = 0; 742 | USB1_ENDPTPRIME |= (1<<16); 743 | while (USB1_ENDPTPRIME) ; 744 | } 745 | endpoint0_transfer_ack.next = 1; 746 | endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0); 747 | endpoint0_transfer_ack.pointer0 = 0; 748 | endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_ack; 749 | endpoint_queue_head[0].status = 0; 750 | USB1_ENDPTCOMPLETE = (1<<0) | (1<<16); 751 | USB1_ENDPTPRIME |= (1<<0); 752 | endpoint0_notify_mask = (notify ? (1 << 0) : 0); 753 | while (USB1_ENDPTPRIME) ; 754 | } 755 | 756 | static void endpoint0_receive(void *data, uint32_t len, int notify) 757 | { 758 | //printf("rx %lu\n", len); 759 | if (len > 0) { 760 | // Executing A Transfer Descriptor, page 3182 761 | endpoint0_transfer_data.next = 1; 762 | endpoint0_transfer_data.status = (len << 16) | (1<<7); 763 | uint32_t addr = (uint32_t)data; 764 | endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159 765 | endpoint0_transfer_data.pointer1 = addr + 4096; 766 | endpoint0_transfer_data.pointer2 = addr + 8192; 767 | endpoint0_transfer_data.pointer3 = addr + 12288; 768 | endpoint0_transfer_data.pointer4 = addr + 16384; 769 | // Case 1: Link list is empty, page 3182 770 | endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_data; 771 | endpoint_queue_head[0].status = 0; 772 | USB1_ENDPTPRIME |= (1<<0); 773 | while (USB1_ENDPTPRIME) ; 774 | } 775 | endpoint0_transfer_ack.next = 1; 776 | endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0); 777 | endpoint0_transfer_ack.pointer0 = 0; 778 | endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_ack; 779 | endpoint_queue_head[1].status = 0; 780 | USB1_ENDPTCOMPLETE = (1<<0) | (1<<16); 781 | USB1_ENDPTPRIME |= (1<<16); 782 | endpoint0_notify_mask = (notify ? (1 << 16) : 0); 783 | while (USB1_ENDPTPRIME) ; 784 | } 785 | 786 | /*typedef union { 787 | struct { 788 | union { 789 | struct { 790 | uint8_t bmRequestType; 791 | uint8_t bRequest; 792 | }; 793 | uint16_t wRequestAndType; 794 | }; 795 | uint16_t wValue; 796 | uint16_t wIndex; 797 | uint16_t wLength; 798 | }; 799 | struct { 800 | uint32_t word1; 801 | uint32_t word2; 802 | }; 803 | uint64_t bothwords; 804 | } setup_t; */ 805 | 806 | 807 | static void endpoint0_complete(void) 808 | { 809 | setup_t setup; 810 | 811 | setup.bothwords = endpoint0_setupdata.bothwords; 812 | //printf("complete %x %x %x\n", setup.word1, setup.word2, endpoint0_buffer[0]); 813 | #ifdef CDC_STATUS_INTERFACE 814 | // 0x2021 is CDC_SET_LINE_CODING 815 | if (setup.wRequestAndType == 0x2021 && setup.wIndex == CDC_STATUS_INTERFACE) { 816 | memcpy(usb_cdc_line_coding, endpoint0_buffer, 7); 817 | printf("usb_cdc_line_coding, baud=%u\n", usb_cdc_line_coding[0]); 818 | if (usb_cdc_line_coding[0] == 134) { 819 | usb_start_sof_interrupts(NUM_INTERFACE); 820 | usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec 821 | } 822 | } 823 | #endif 824 | #ifdef CDC2_STATUS_INTERFACE 825 | if (setup.wRequestAndType == 0x2021 && setup.wIndex == CDC2_STATUS_INTERFACE) { 826 | memcpy(usb_cdc2_line_coding, endpoint0_buffer, 7); 827 | printf("usb_cdc2_line_coding, baud=%u\n", usb_cdc2_line_coding[0]); 828 | if (usb_cdc2_line_coding[0] == 134) { 829 | usb_start_sof_interrupts(NUM_INTERFACE); 830 | usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec 831 | } 832 | } 833 | #endif 834 | #ifdef CDC3_STATUS_INTERFACE 835 | if (setup.wRequestAndType == 0x2021 && setup.wIndex == CDC3_STATUS_INTERFACE) { 836 | memcpy(usb_cdc3_line_coding, endpoint0_buffer, 7); 837 | printf("usb_cdc3_line_coding, baud=%u\n", usb_cdc3_line_coding[0]); 838 | if (usb_cdc3_line_coding[0] == 134) { 839 | usb_start_sof_interrupts(NUM_INTERFACE); 840 | usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec 841 | } 842 | } 843 | #endif 844 | #ifdef KEYBOARD_INTERFACE 845 | if (setup.word1 == 0x02000921 && setup.word2 == ((1 << 16) | KEYBOARD_INTERFACE)) { 846 | keyboard_leds = endpoint0_buffer[0]; 847 | endpoint0_transmit(NULL, 0, 0); 848 | } 849 | #endif 850 | #ifdef SEREMU_INTERFACE 851 | if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE)) { 852 | if (endpoint0_buffer[0] == 0xA9 && endpoint0_buffer[1] == 0x45 853 | && endpoint0_buffer[2] == 0xC2 && endpoint0_buffer[3] == 0x6B) { 854 | printf("seremu reboot request\n"); 855 | usb_start_sof_interrupts(NUM_INTERFACE); 856 | usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec 857 | } else { 858 | // any other feature report means Arduino Serial Monitor is open 859 | usb_seremu_online = 1; 860 | } 861 | } 862 | #endif 863 | #ifdef AUDIO_INTERFACE 864 | if (setup.word1 == 0x02010121 || setup.word1 == 0x01000121 /* TODO: check setup.word2 */) { 865 | usb_audio_set_feature(&endpoint0_setupdata, endpoint0_buffer); 866 | } 867 | #endif 868 | #ifdef MTP_INTERFACE 869 | if (setup.wRequestAndType == 0x6421) { 870 | if (endpoint0_buffer[0] == 0x01 && endpoint0_buffer[1] == 0x40) { 871 | printf("MTP cancel, transaction ID=%08X\n", 872 | endpoint0_buffer[2] | (endpoint0_buffer[3] << 8) | 873 | (endpoint0_buffer[4] << 16) | (endpoint0_buffer[5] << 24)); 874 | usb_mtp_status = 0x19; // 0x19 = host initiated cancel 875 | } 876 | } 877 | #endif 878 | #ifdef XINPUT_INTERFACE 879 | // dummy reads to suppress '-Wunused-but-set-variable' and '-Wunused-variable' warnings from GCC 880 | (void) setup.wIndex; 881 | (void) endpoint0_buffer; 882 | #endif 883 | } 884 | 885 | static void usb_endpoint_config(endpoint_t *qh, uint32_t config, void (*callback)(transfer_t *)) 886 | { 887 | memset(qh, 0, sizeof(endpoint_t)); 888 | qh->config = config; 889 | qh->next = 1; // Terminate bit = 1 890 | qh->callback_function = callback; 891 | } 892 | 893 | void usb_config_rx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *)) 894 | { 895 | uint32_t config = (packet_size << 16) | (do_zlp ? 0 : (1 << 29)); 896 | if (ep < 1 || ep > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 897 | usb_endpoint_config(endpoint_queue_head + ep * 2, config, cb); 898 | if (cb) endpointN_notify_mask |= (1 << ep); 899 | } 900 | 901 | void usb_config_tx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *)) 902 | { 903 | uint32_t config = (packet_size << 16) | (do_zlp ? 0 : (1 << 29)); 904 | if (ep < 1 || ep > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 905 | usb_endpoint_config(endpoint_queue_head + ep * 2 + 1, config, cb); 906 | if (cb) endpointN_notify_mask |= (1 << (ep + 16)); 907 | } 908 | 909 | void usb_config_rx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)) 910 | { 911 | if (mult < 1 || mult > 3) return; 912 | uint32_t config = (packet_size << 16) | (mult << 30); 913 | if (ep < 1 || ep > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 914 | usb_endpoint_config(endpoint_queue_head + ep * 2, config, cb); 915 | if (cb) endpointN_notify_mask |= (1 << ep); 916 | } 917 | 918 | void usb_config_tx_iso(uint32_t ep, uint32_t packet_size, int mult, void (*cb)(transfer_t *)) 919 | { 920 | if (mult < 1 || mult > 3) return; 921 | uint32_t config = (packet_size << 16) | (mult << 30); 922 | if (ep < 1 || ep > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 923 | usb_endpoint_config(endpoint_queue_head + ep * 2 + 1, config, cb); 924 | if (cb) endpointN_notify_mask |= (1 << (ep + 16)); 925 | } 926 | 927 | 928 | 929 | void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param) 930 | { 931 | transfer->next = 1; 932 | transfer->status = (len << 16) | (1<<7); 933 | uint32_t addr = (uint32_t)data; 934 | transfer->pointer0 = addr; 935 | transfer->pointer1 = addr + 4096; 936 | transfer->pointer2 = addr + 8192; 937 | transfer->pointer3 = addr + 12288; 938 | transfer->pointer4 = addr + 16384; 939 | transfer->callback_param = param; 940 | } 941 | 942 | #if 0 943 | void usb_print_transfer_log(void) 944 | { 945 | uint32_t i, count; 946 | printf("log %d transfers\n", transfer_log_count); 947 | count = transfer_log_count; 948 | if (count > LOG_SIZE) count = LOG_SIZE; 949 | 950 | for (i=0; i < count; i++) { 951 | if (transfer_log_head == 0) transfer_log_head = LOG_SIZE; 952 | transfer_log_head--; 953 | uint32_t log = transfer_log[transfer_log_head]; 954 | printf(" %c %X\n", log >> 8, (int)(log & 255)); 955 | } 956 | } 957 | #endif 958 | 959 | static void schedule_transfer(endpoint_t *endpoint, uint32_t epmask, transfer_t *transfer) 960 | { 961 | // when we stop at 6, why is the last transfer missing from the USB output? 962 | //if (transfer_log_count >= 6) return; 963 | 964 | //uint32_t ret = (*(const uint8_t *)transfer->pointer0) << 8; 965 | if (endpoint->callback_function) { 966 | transfer->status |= (1<<15); 967 | } 968 | __disable_irq(); 969 | //digitalWriteFast(1, HIGH); 970 | // Executing A Transfer Descriptor, page 2468 (RT1060 manual, Rev 1, 12/2018) 971 | transfer_t *last = endpoint->last_transfer; 972 | if (last) { 973 | last->next = (uint32_t)transfer; 974 | if (USB1_ENDPTPRIME & epmask) goto end; 975 | //digitalWriteFast(2, HIGH); 976 | //ret |= 0x01; 977 | uint32_t status, cyccnt=ARM_DWT_CYCCNT; 978 | do { 979 | USB1_USBCMD |= USB_USBCMD_ATDTW; 980 | status = USB1_ENDPTSTATUS; 981 | } while (!(USB1_USBCMD & USB_USBCMD_ATDTW) && (ARM_DWT_CYCCNT - cyccnt < 2400)); 982 | //USB1_USBCMD &= ~USB_USBCMD_ATDTW; 983 | if (status & epmask) goto end; 984 | //ret |= 0x02; 985 | endpoint->next = (uint32_t)transfer; 986 | endpoint->status = 0; 987 | USB1_ENDPTPRIME |= epmask; 988 | goto end; 989 | } 990 | //digitalWriteFast(4, HIGH); 991 | endpoint->next = (uint32_t)transfer; 992 | endpoint->status = 0; 993 | USB1_ENDPTPRIME |= epmask; 994 | endpoint->first_transfer = transfer; 995 | end: 996 | endpoint->last_transfer = transfer; 997 | __enable_irq(); 998 | //digitalWriteFast(4, LOW); 999 | //digitalWriteFast(3, LOW); 1000 | //digitalWriteFast(2, LOW); 1001 | //digitalWriteFast(1, LOW); 1002 | //if (transfer_log_head > LOG_SIZE) transfer_log_head = 0; 1003 | //transfer_log[transfer_log_head++] = ret; 1004 | //transfer_log_count++; 1005 | } 1006 | // ENDPTPRIME - Software should write a one to the corresponding bit when 1007 | // posting a new transfer descriptor to an endpoint queue head. 1008 | // Hardware automatically uses this bit to begin parsing for a 1009 | // new transfer descriptor from the queue head and prepare a 1010 | // transmit buffer. Hardware clears this bit when the associated 1011 | // endpoint(s) is (are) successfully primed. 1012 | // Momentarily set by hardware during hardware re-priming 1013 | // operations when a dTD is retired, and the dQH is updated. 1014 | 1015 | // ENDPTSTATUS - Transmit Buffer Ready - set to one by the hardware as a 1016 | // response to receiving a command from a corresponding bit 1017 | // in the ENDPTPRIME register. . Buffer ready is cleared by 1018 | // USB reset, by the USB DMA system, or through the ENDPTFLUSH 1019 | // register. (so 0=buffer ready, 1=buffer primed for transmit) 1020 | 1021 | // USBCMD.ATDTW - This bit is used as a semaphore to ensure proper addition 1022 | // of a new dTD to an active (primed) endpoint's linked list. 1023 | // This bit is set and cleared by software. 1024 | // This bit would also be cleared by hardware when state machine 1025 | // is hazard region for which adding a dTD to a primed endpoint 1026 | // may go unrecognized. 1027 | 1028 | /*struct endpoint_struct { 1029 | uint32_t config; 1030 | uint32_t current; 1031 | uint32_t next; 1032 | uint32_t status; 1033 | uint32_t pointer0; 1034 | uint32_t pointer1; 1035 | uint32_t pointer2; 1036 | uint32_t pointer3; 1037 | uint32_t pointer4; 1038 | uint32_t reserved; 1039 | uint32_t setup0; 1040 | uint32_t setup1; 1041 | transfer_t *first_transfer; 1042 | transfer_t *last_transfer; 1043 | void (*callback_function)(transfer_t *completed_transfer); 1044 | uint32_t unused1; 1045 | };*/ 1046 | 1047 | static void run_callbacks(endpoint_t *ep) 1048 | { 1049 | //printf("run_callbacks\n"); 1050 | transfer_t *first = ep->first_transfer; 1051 | if (first == NULL) return; 1052 | 1053 | // count how many transfers are completed, then remove them from the endpoint's list 1054 | uint32_t count = 0; 1055 | transfer_t *t = first; 1056 | while (1) { 1057 | if (t->status & (1<<7)) { 1058 | // found a still-active transfer, new list begins here 1059 | //printf(" still active\n"); 1060 | ep->first_transfer = t; 1061 | break; 1062 | } 1063 | count++; 1064 | t = (transfer_t *)t->next; 1065 | if ((uint32_t)t == 1) { 1066 | // reached end of list, all need callbacks, new list is empty 1067 | //printf(" end of list\n"); 1068 | ep->first_transfer = NULL; 1069 | ep->last_transfer = NULL; 1070 | break; 1071 | } 1072 | } 1073 | // do all the callbacks 1074 | while (count) { 1075 | transfer_t *next = (transfer_t *)first->next; 1076 | ep->callback_function(first); 1077 | first = next; 1078 | count--; 1079 | } 1080 | } 1081 | 1082 | void usb_transmit(int endpoint_number, transfer_t *transfer) 1083 | { 1084 | if (endpoint_number < 1 || endpoint_number > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 1085 | endpoint_t *endpoint = endpoint_queue_head + endpoint_number * 2 + 1; 1086 | uint32_t mask = 1 << (endpoint_number + 16); 1087 | schedule_transfer(endpoint, mask, transfer); 1088 | } 1089 | 1090 | void usb_receive(int endpoint_number, transfer_t *transfer) 1091 | { 1092 | if (endpoint_number < 1 || endpoint_number > NUM_ENDPOINTS) return; // XInput, allow access to endpoint 1 1093 | endpoint_t *endpoint = endpoint_queue_head + endpoint_number * 2; 1094 | uint32_t mask = 1 << endpoint_number; 1095 | schedule_transfer(endpoint, mask, transfer); 1096 | } 1097 | 1098 | uint32_t usb_transfer_status(const transfer_t *transfer) 1099 | { 1100 | #if defined(USB_MTPDISK) || defined(USB_MTPDISK_SERIAL) 1101 | uint32_t status, cmd; 1102 | //int count=0; 1103 | cmd = USB1_USBCMD; 1104 | while (1) { 1105 | __disable_irq(); 1106 | USB1_USBCMD = cmd | USB_USBCMD_ATDTW; 1107 | status = transfer->status; 1108 | cmd = USB1_USBCMD; 1109 | __enable_irq(); 1110 | if (cmd & USB_USBCMD_ATDTW) return status; 1111 | //if (!(cmd & USB_USBCMD_ATDTW)) continue; 1112 | //if (status & 0x80) break; // for still active, only 1 reading needed 1113 | //if (++count > 1) break; // for completed, check 10 times 1114 | } 1115 | #else 1116 | return transfer->status; 1117 | #endif 1118 | } 1119 | 1120 | #else // defined(NUM_ENDPOINTS) 1121 | 1122 | void usb_init(void) 1123 | { 1124 | } 1125 | 1126 | #endif // defined(NUM_ENDPOINTS) 1127 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/usb_inst.cpp: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #include 32 | #include "usb_desc.h" 33 | 34 | #if F_CPU >= 20000000 35 | 36 | #ifdef CDC_DATA_INTERFACE 37 | #ifdef CDC_STATUS_INTERFACE 38 | usb_serial_class Serial; 39 | #endif 40 | #endif 41 | 42 | #ifdef CDC2_DATA_INTERFACE 43 | #ifdef CDC2_STATUS_INTERFACE 44 | usb_serial2_class SerialUSB1; 45 | #endif 46 | #endif 47 | 48 | #ifdef CDC3_DATA_INTERFACE 49 | #ifdef CDC3_STATUS_INTERFACE 50 | usb_serial3_class SerialUSB2; 51 | #endif 52 | #endif 53 | 54 | #ifdef MIDI_INTERFACE 55 | usb_midi_class usbMIDI; 56 | #endif 57 | 58 | #ifdef KEYBOARD_INTERFACE 59 | usb_keyboard_class Keyboard; 60 | #endif 61 | 62 | #ifdef MOUSE_INTERFACE 63 | usb_mouse_class Mouse; 64 | #endif 65 | 66 | #ifdef RAWHID_INTERFACE 67 | usb_rawhid_class RawHID; 68 | #endif 69 | 70 | #ifdef FLIGHTSIM_INTERFACE 71 | FlightSimClass FlightSim; 72 | #endif 73 | 74 | #ifdef SEREMU_INTERFACE 75 | usb_seremu_class Serial; 76 | #endif 77 | 78 | #ifdef JOYSTICK_INTERFACE 79 | usb_joystick_class Joystick; 80 | uint8_t usb_joystick_class::manual_mode = 0; 81 | #endif 82 | 83 | #ifdef USB_DISABLED 84 | usb_serial_class Serial; 85 | #endif 86 | 87 | #if defined(USB_XINPUT) 88 | usb_serial_class Serial; 89 | #endif 90 | 91 | 92 | #else // F_CPU < 20 MHz 93 | 94 | #if defined(USB_SERIAL) || defined(USB_SERIAL_HID) 95 | usb_serial_class Serial; 96 | #elif (USB_DISABLED) 97 | usb_serial_class Serial; 98 | #else 99 | usb_seremu_class Serial; 100 | #endif 101 | 102 | #endif // F_CPU 103 | 104 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/usb_serial.h: -------------------------------------------------------------------------------- 1 | /* Teensyduino Core Library 2 | * http://www.pjrc.com/teensy/ 3 | * Copyright (c) 2017 PJRC.COM, LLC. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining 6 | * a copy of this software and associated documentation files (the 7 | * "Software"), to deal in the Software without restriction, including 8 | * without limitation the rights to use, copy, modify, merge, publish, 9 | * distribute, sublicense, and/or sell copies of the Software, and to 10 | * permit persons to whom the Software is furnished to do so, subject to 11 | * the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * 2. If the Software is incorporated into a build system that allows 17 | * selection among a list of target devices, then similar target 18 | * devices manufactured by PJRC.COM must be included in the list of 19 | * target devices and selectable in the same manner. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include "usb_desc.h" 34 | #include 35 | 36 | #if (defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)) || defined(USB_DISABLED) || defined(USB_XINPUT) 37 | 38 | #if !(defined(USB_DISABLED) || defined(USB_XINPUT)) 39 | 40 | // C language implementation 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | void usb_serial_reset(void); 45 | void usb_serial_configure(void); 46 | int usb_serial_getchar(void); 47 | int usb_serial_peekchar(void); 48 | int usb_serial_available(void); 49 | int usb_serial_read(void *buffer, uint32_t size); 50 | void usb_serial_flush_input(void); 51 | int usb_serial_putchar(uint8_t c); 52 | int usb_serial_write(const void *buffer, uint32_t size); 53 | int usb_serial_write_buffer_free(void); 54 | void usb_serial_flush_output(void); 55 | extern uint32_t usb_cdc_line_coding[2]; 56 | extern volatile uint32_t usb_cdc_line_rtsdtr_millis; 57 | extern volatile uint32_t systick_millis_count; 58 | extern volatile uint8_t usb_cdc_line_rtsdtr; 59 | extern volatile uint8_t usb_cdc_transmit_flush_timer; 60 | extern volatile uint8_t usb_configuration; 61 | extern void serialEvent(void) __attribute__((weak)); 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #define USB_SERIAL_DTR 0x01 67 | #define USB_SERIAL_RTS 0x02 68 | 69 | // C++ interface 70 | #ifdef __cplusplus 71 | #include "Stream.h" 72 | class usb_serial_class : public Stream 73 | { 74 | public: 75 | constexpr usb_serial_class() {} 76 | // Serial.begin(baud) is optional on Teensy. The main USB device port 77 | // is always initialized early during startup. The baud rate setting 78 | // is not used. Communication occurs at USB native speed. For 79 | // compatibility with Arduino code, Serial.begin waits up to 2 seconds 80 | // for your PC to open the virtual serial port. 81 | void begin(long baud_unused __attribute__((unused))) { 82 | uint32_t millis_begin = systick_millis_count; 83 | while (!(*this)) { 84 | uint32_t elapsed = systick_millis_count - millis_begin; 85 | if (usb_configuration) { 86 | // Wait up to 2 seconds for Arduino Serial Monitor 87 | if (elapsed > 2000) break; 88 | } else { 89 | // But wait only 3/4 second if there is no sign the 90 | // USB host has begun the USB enumeration process. 91 | if (elapsed > 750) break; 92 | } 93 | yield(); 94 | } 95 | } 96 | void end() { /* TODO: flush output and shut down USB port */ }; 97 | // Returns the number of bytes which have been received from your PC and 98 | // can be fetched using Serial.read() or Serial.readBytes(). 99 | virtual int available() { return usb_serial_available(); } 100 | // Reads the next received byte, or returns -1 if nothing has been received 101 | // from your PC. 102 | virtual int read() { return usb_serial_getchar(); } 103 | // Returns the next received byte, but does not remove it from the receive 104 | // buffer. Returns -1 if nothing has been received from your PC. 105 | virtual int peek() { return usb_serial_peekchar(); } 106 | // Wait for all data written by print() or write() to actually transmit to 107 | // your PC. On Teensy 4, this function has a known limitation where it 108 | // returns early, when buffered data has been given to Teensy's USB device 109 | // controller, but before your PC's USB host controller actually transfers 110 | // the data across your USB cable. 111 | virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB... 112 | // Discard all received data which has not been read. 113 | virtual void clear(void) { usb_serial_flush_input(); } 114 | // Transmit a single byte to your PC 115 | virtual size_t write(uint8_t c) { return usb_serial_putchar(c); } 116 | // Transmit a buffer containing any number of bytes to your PC 117 | virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); } 118 | // Transmit a single byte to your PC 119 | size_t write(unsigned long n) { return write((uint8_t)n); } 120 | // Transmit a single byte to your PC 121 | size_t write(long n) { return write((uint8_t)n); } 122 | // Transmit a single byte to your PC 123 | size_t write(unsigned int n) { return write((uint8_t)n); } 124 | // Transmit a single byte to your PC 125 | size_t write(int n) { return write((uint8_t)n); } 126 | // Returns the number of bytes which may be transmitted by write() or print() 127 | // without waiting. Typically programs which must maintain rapid checking 128 | // and response to sensors use availableForWrite() to decide whether to 129 | // transmit. 130 | virtual int availableForWrite() { return usb_serial_write_buffer_free(); } 131 | using Print::write; 132 | // Cause any previously transmitted data written to buffers to be actually 133 | // sent over the USB cable to your PC as soon as possible. Normally writes 134 | // are combined to efficiently use maximum size USB packets. Use of send_now() 135 | // minimizes latency, but excessive use can lead to inefficient utilization 136 | // of USB bandwidth. 137 | void send_now(void) { usb_serial_flush_output(); } 138 | // Returns the baud rate configuration set by PC software. This setting is 139 | // not used for USB communication. You would typically call this function 140 | // when making a USB to Serial converter, where you wish to know the baud 141 | // rate software on the PC intends for you to configure on the serial port. 142 | uint32_t baud(void) { return usb_cdc_line_coding[0]; } 143 | // Returns the baud rate configuration set by PC software. This setting is 144 | // not used for USB communication. You would typically call this function 145 | // when making a USB to Serial converter, where you wish to know the baud 146 | // rate software on the PC intends for you to configure on the serial port. 147 | uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; } 148 | // Returns the number of stop bits configuration set by PC software. This 149 | // setting is not used for USB communication. You would typically call this 150 | // function when making a USB to Serial converter, where you wish to know how 151 | // the PC software intends for you to configure the serial port. 152 | uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even 153 | // Returns the number of data bits configuration set by PC software. 154 | // 0=none, 1=odd, 2=even. This setting is not used for USB communication, 155 | // which always checks for errors at the USB packet level. You would typically 156 | // call this function when making a USB to Serial converter, where you wish 157 | // to know how the PC software intends for you to configure the serial port. 158 | uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; } 159 | // Returns the current state of the virtual serial DTR signal. 160 | uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } 161 | // Returns the current state of the virtual serial RTS signal. 162 | uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } 163 | // Testing Serial as a boolean indicates whether USB is active and a program 164 | // running on your PC has raised the DTR signal, which typically means it has 165 | // opened the port and is ready to communicate. 166 | operator bool() { 167 | yield(); 168 | return usb_configuration && (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) && 169 | ((uint32_t)(systick_millis_count - usb_cdc_line_rtsdtr_millis) >= 15); 170 | } 171 | // Read up to length bytes into a buffer. readBytes() will wait up to 172 | // the number of milliseconds configured by setTimeout(). The return value 173 | // is the number of bytes actually read, which may be zero if your PC 174 | // does not send anything. To read without waiting, configure setTimeout(0). 175 | size_t readBytes(char *buffer, size_t length) { 176 | size_t count=0; 177 | unsigned long startMillis = millis(); 178 | do { 179 | count += usb_serial_read(buffer + count, length - count); 180 | if (count >= length) return count; 181 | } while(millis() - startMillis < _timeout); 182 | setReadError(); 183 | return count; 184 | } 185 | 186 | }; 187 | // Serial provides USB Virtual Serial communication with your computer. 188 | extern usb_serial_class Serial; 189 | #endif // __cplusplus 190 | 191 | #else // !defined(USB_DISABLED) 192 | 193 | // Allow Arduino programs using Serial to compile, but Serial will do nothing. 194 | #ifdef __cplusplus 195 | #include "Stream.h" 196 | class usb_serial_class : public Stream 197 | { 198 | public: 199 | constexpr usb_serial_class() {} 200 | void begin(long) { }; 201 | void end() { }; 202 | virtual int available() { return 0; } 203 | virtual int read() { return -1; } 204 | virtual int peek() { return -1; } 205 | virtual void flush() { } 206 | virtual void clear() { } 207 | virtual size_t write(uint8_t c) { return 1; } 208 | virtual size_t write(const uint8_t *buffer, size_t size) { return size; } 209 | size_t write(unsigned long n) { return 1; } 210 | size_t write(long n) { return 1; } 211 | size_t write(unsigned int n) { return 1; } 212 | size_t write(int n) { return 1; } 213 | virtual int availableForWrite() { return 0; } 214 | using Print::write; 215 | void send_now(void) { } 216 | uint32_t baud(void) { return 0; } 217 | uint8_t stopbits(void) { return 1; } 218 | uint8_t paritytype(void) { return 0; } 219 | uint8_t numbits(void) { return 8; } 220 | uint8_t dtr(void) { return 1; } 221 | uint8_t rts(void) { return 1; } 222 | operator bool() { return true; } 223 | }; 224 | 225 | extern usb_serial_class Serial; 226 | extern void serialEvent(void) __attribute__((weak)); 227 | #endif // __cplusplus 228 | 229 | #endif // !defined(USB_DISABLED) 230 | 231 | #endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE 232 | 233 | 234 | 235 | 236 | #if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE) 237 | 238 | // C language implementation 239 | #ifdef __cplusplus 240 | extern "C" { 241 | #endif 242 | void usb_serial2_configure(void); 243 | int usb_serial2_getchar(void); 244 | int usb_serial2_peekchar(void); 245 | int usb_serial2_available(void); 246 | int usb_serial2_read(void *buffer, uint32_t size); 247 | void usb_serial2_flush_input(void); 248 | int usb_serial2_putchar(uint8_t c); 249 | int usb_serial2_write(const void *buffer, uint32_t size); 250 | int usb_serial2_write_buffer_free(void); 251 | void usb_serial2_flush_output(void); 252 | extern uint32_t usb_cdc2_line_coding[2]; 253 | extern volatile uint32_t usb_cdc2_line_rtsdtr_millis; 254 | extern volatile uint8_t usb_cdc2_line_rtsdtr; 255 | extern volatile uint8_t usb_cdc2_transmit_flush_timer; 256 | extern void serialEventUSB1(void) __attribute__((weak)); 257 | #ifdef __cplusplus 258 | } 259 | #endif 260 | 261 | // C++ interface 262 | #ifdef __cplusplus 263 | #include "Stream.h" 264 | class usb_serial2_class : public Stream 265 | { 266 | public: 267 | constexpr usb_serial2_class() {} 268 | void begin(long) { 269 | //uint32_t millis_begin = systick_millis_count; 270 | //disabled for now - causes more trouble than it solves? 271 | //while (!(*this)) { 272 | // wait up to 2.5 seconds for Arduino Serial Monitor 273 | // Yes, this is a long time, but some Windows systems open 274 | // the port very slowly. This wait allows programs for 275 | // Arduino Uno to "just work" (without forcing a reboot when 276 | // the port is opened), and when no PC is connected the user's 277 | // sketch still gets to run normally after this wait time. 278 | //if ((uint32_t)(systick_millis_count - millis_begin) > 2500) break; 279 | //} 280 | } 281 | void end() { /* TODO: flush output and shut down USB port */ }; 282 | virtual int available() { return usb_serial2_available(); } 283 | virtual int read() { return usb_serial2_getchar(); } 284 | virtual int peek() { return usb_serial2_peekchar(); } 285 | virtual void flush() { usb_serial2_flush_output(); } // TODO: actually wait for data to leave USB... 286 | virtual void clear(void) { usb_serial2_flush_input(); } 287 | virtual size_t write(uint8_t c) { return usb_serial2_putchar(c); } 288 | virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial2_write(buffer, size); } 289 | size_t write(unsigned long n) { return write((uint8_t)n); } 290 | size_t write(long n) { return write((uint8_t)n); } 291 | size_t write(unsigned int n) { return write((uint8_t)n); } 292 | size_t write(int n) { return write((uint8_t)n); } 293 | virtual int availableForWrite() { return usb_serial2_write_buffer_free(); } 294 | using Print::write; 295 | void send_now(void) { usb_serial2_flush_output(); } 296 | uint32_t baud(void) { return usb_cdc2_line_coding[0]; } 297 | uint8_t stopbits(void) { uint8_t b = usb_cdc2_line_coding[1]; if (!b) b = 1; return b; } 298 | uint8_t paritytype(void) { return usb_cdc2_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even 299 | uint8_t numbits(void) { return usb_cdc2_line_coding[1] >> 16; } 300 | uint8_t dtr(void) { return (usb_cdc2_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } 301 | uint8_t rts(void) { return (usb_cdc2_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } 302 | operator bool() { 303 | yield(); 304 | return usb_configuration && (usb_cdc2_line_rtsdtr & USB_SERIAL_DTR) && 305 | ((uint32_t)(systick_millis_count - usb_cdc2_line_rtsdtr_millis) >= 15); 306 | } 307 | size_t readBytes(char *buffer, size_t length) { 308 | size_t count=0; 309 | unsigned long startMillis = millis(); 310 | do { 311 | count += usb_serial2_read(buffer + count, length - count); 312 | if (count >= length) return count; 313 | } while(millis() - startMillis < _timeout); 314 | setReadError(); 315 | return count; 316 | } 317 | 318 | }; 319 | extern usb_serial2_class SerialUSB1; 320 | #endif // __cplusplus 321 | 322 | #endif // CDC2_STATUS_INTERFACE && CDC2_DATA_INTERFACE 323 | 324 | 325 | 326 | #if defined(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE) 327 | 328 | // C language implementation 329 | #ifdef __cplusplus 330 | extern "C" { 331 | #endif 332 | void usb_serial3_configure(void); 333 | int usb_serial3_getchar(void); 334 | int usb_serial3_peekchar(void); 335 | int usb_serial3_available(void); 336 | int usb_serial3_read(void *buffer, uint32_t size); 337 | void usb_serial3_flush_input(void); 338 | int usb_serial3_putchar(uint8_t c); 339 | int usb_serial3_write(const void *buffer, uint32_t size); 340 | int usb_serial3_write_buffer_free(void); 341 | void usb_serial3_flush_output(void); 342 | extern uint32_t usb_cdc3_line_coding[2]; 343 | extern volatile uint32_t usb_cdc3_line_rtsdtr_millis; 344 | extern volatile uint8_t usb_cdc3_line_rtsdtr; 345 | extern volatile uint8_t usb_cdc3_transmit_flush_timer; 346 | extern void serialEventUSB2(void) __attribute__((weak)); 347 | #ifdef __cplusplus 348 | } 349 | #endif 350 | 351 | // C++ interface 352 | #ifdef __cplusplus 353 | #include "Stream.h" 354 | class usb_serial3_class : public Stream 355 | { 356 | public: 357 | constexpr usb_serial3_class() {} 358 | void begin(long) { 359 | //uint32_t millis_begin = systick_millis_count; 360 | //disabled for now - causes more trouble than it solves? 361 | //while (!(*this)) { 362 | // wait up to 2.5 seconds for Arduino Serial Monitor 363 | // Yes, this is a long time, but some Windows systems open 364 | // the port very slowly. This wait allows programs for 365 | // Arduino Uno to "just work" (without forcing a reboot when 366 | // the port is opened), and when no PC is connected the user's 367 | // sketch still gets to run normally after this wait time. 368 | //if ((uint32_t)(systick_millis_count - millis_begin) > 2500) break; 369 | //} 370 | } 371 | void end() { /* TODO: flush output and shut down USB port */ }; 372 | virtual int available() { return usb_serial3_available(); } 373 | virtual int read() { return usb_serial3_getchar(); } 374 | virtual int peek() { return usb_serial3_peekchar(); } 375 | virtual void flush() { usb_serial3_flush_output(); } // TODO: actually wait for data to leave USB... 376 | virtual void clear(void) { usb_serial3_flush_input(); } 377 | virtual size_t write(uint8_t c) { return usb_serial3_putchar(c); } 378 | virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial3_write(buffer, size); } 379 | size_t write(unsigned long n) { return write((uint8_t)n); } 380 | size_t write(long n) { return write((uint8_t)n); } 381 | size_t write(unsigned int n) { return write((uint8_t)n); } 382 | size_t write(int n) { return write((uint8_t)n); } 383 | virtual int availableForWrite() { return usb_serial3_write_buffer_free(); } 384 | using Print::write; 385 | void send_now(void) { usb_serial3_flush_output(); } 386 | uint32_t baud(void) { return usb_cdc3_line_coding[0]; } 387 | uint8_t stopbits(void) { uint8_t b = usb_cdc3_line_coding[1]; if (!b) b = 1; return b; } 388 | uint8_t paritytype(void) { return usb_cdc3_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even 389 | uint8_t numbits(void) { return usb_cdc3_line_coding[1] >> 16; } 390 | uint8_t dtr(void) { return (usb_cdc3_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } 391 | uint8_t rts(void) { return (usb_cdc3_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } 392 | operator bool() { 393 | yield(); 394 | return usb_configuration && (usb_cdc3_line_rtsdtr & USB_SERIAL_DTR) && 395 | ((uint32_t)(systick_millis_count - usb_cdc3_line_rtsdtr_millis) >= 15); 396 | } 397 | size_t readBytes(char *buffer, size_t length) { 398 | size_t count=0; 399 | unsigned long startMillis = millis(); 400 | do { 401 | count += usb_serial3_read(buffer + count, length - count); 402 | if (count >= length) return count; 403 | } while(millis() - startMillis < _timeout); 404 | setReadError(); 405 | return count; 406 | } 407 | 408 | }; 409 | extern usb_serial3_class SerialUSB2; 410 | #endif // __cplusplus 411 | 412 | #endif // CDC3_STATUS_INTERFACE && CDC3_DATA_INTERFACE 413 | 414 | 415 | 416 | 417 | 418 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/usb_xinput.c: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016 Zachery Littell 4 | * Modified (c) 2019 David Madison 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "usb_dev.h" 26 | #include "usb_xinput.h" 27 | #include "core_pins.h" // for yield(), millis() 28 | #include // for memcpy() 29 | #include "avr/pgmspace.h" // for DMAMEM 30 | 31 | #ifdef XINPUT_INTERFACE // defined by usb_dev.h -> usb_desc.h 32 | 33 | #define TX_NUM 4 34 | #define TX_TIMEOUT_MSEC 250 35 | #define TX_BUFSIZE 32 36 | static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32))); 37 | DMAMEM static uint8_t txbuffer[TX_NUM * TX_BUFSIZE] __attribute__ ((aligned(32))); 38 | static uint8_t tx_head=0; 39 | static uint8_t transmit_previous_timeout=0; 40 | 41 | 42 | #define RX_NUM 6 43 | static transfer_t rx_transfer[RX_NUM] __attribute__ ((used, aligned(32))); 44 | DMAMEM static uint8_t rx_buffer[RX_NUM * XINPUT_RX_SIZE] __attribute__ ((aligned(32))); 45 | static uint16_t rx_count[RX_NUM]; 46 | static volatile uint8_t rx_head; 47 | static volatile uint8_t rx_tail; 48 | static uint8_t rx_list[RX_NUM + 1]; 49 | static volatile uint32_t rx_available; 50 | static volatile uint8_t in_rx_event = 0; 51 | static void rx_queue_transfer(int i); 52 | static void rx_event(transfer_t *t); 53 | 54 | void (*usb_xinput_recv_callback)(void) = NULL; 55 | 56 | 57 | static void rx_queue_transfer(int i) 58 | { 59 | NVIC_DISABLE_IRQ(IRQ_USB1); 60 | void *buffer = rx_buffer + i * XINPUT_RX_SIZE; 61 | usb_prepare_transfer(rx_transfer + i, buffer, XINPUT_RX_SIZE, i); 62 | arm_dcache_delete(buffer, XINPUT_RX_SIZE); 63 | usb_receive(XINPUT_RX_ENDPOINT, rx_transfer + i); 64 | NVIC_ENABLE_IRQ(IRQ_USB1); 65 | } 66 | 67 | // called by USB interrupt when any packet is received 68 | static void rx_event(transfer_t *t) 69 | { 70 | int len = XINPUT_RX_SIZE - ((t->status >> 16) & 0x7FFF); 71 | int i = t->callback_param; 72 | if (len > 0) { 73 | uint32_t head = rx_head; 74 | rx_count[i] = len; 75 | if (++head > RX_NUM) head = 0; 76 | rx_list[head] = i; 77 | rx_head = head; 78 | rx_available += len; 79 | 80 | if (usb_xinput_recv_callback) 81 | { 82 | in_rx_event = 1; 83 | usb_xinput_recv_callback(); 84 | in_rx_event = 0; 85 | } 86 | 87 | } else { 88 | // received a zero length packet 89 | rx_queue_transfer(i); 90 | } 91 | } 92 | 93 | void usb_xinput_configure() 94 | { 95 | memset(tx_transfer, 0, sizeof(tx_transfer)); 96 | tx_head = 0; 97 | usb_config_tx(XINPUT_TX_ENDPOINT, XINPUT_TX_SIZE, 0, NULL); 98 | 99 | memset(rx_transfer, 0, sizeof(rx_transfer)); 100 | memset(rx_count, 0, sizeof(rx_count)); 101 | rx_head = 0; 102 | rx_tail = 0; 103 | rx_available = 0; 104 | in_rx_event = 0; 105 | usb_config_rx(XINPUT_RX_ENDPOINT, XINPUT_RX_SIZE, 0, rx_event); 106 | for (int i=0; i < RX_NUM; i++) rx_queue_transfer(i); 107 | } 108 | 109 | extern volatile uint8_t usb_configuration; 110 | 111 | // Function returns whether the microcontroller's USB 112 | // is configured or not (connected to driver) 113 | bool usb_xinput_connected(void) 114 | { 115 | return usb_configuration; 116 | } 117 | 118 | // Function to check if packets are available 119 | // to be received on the RX endpoint 120 | uint16_t usb_xinput_available(void) 121 | { 122 | return rx_available; 123 | } 124 | 125 | 126 | // Function receives packets from the RX endpoint 127 | int usb_xinput_recv(void *buffer, uint8_t nbytes) 128 | { 129 | int count = 0; 130 | 131 | if (!in_rx_event) 132 | NVIC_DISABLE_IRQ(IRQ_USB1); 133 | 134 | uint32_t tail = rx_tail; 135 | if (tail != rx_head) 136 | { 137 | if (++tail > RX_NUM) tail = 0; 138 | uint32_t ii = rx_list[tail]; 139 | 140 | count = rx_count[ii]; 141 | if (nbytes < count) 142 | count = nbytes; 143 | 144 | uint8_t* p = rx_buffer + ii * XINPUT_RX_SIZE; 145 | memcpy(buffer, p, count); 146 | 147 | rx_available -= rx_count[ii]; 148 | rx_tail = tail; 149 | rx_queue_transfer(ii); 150 | } 151 | 152 | if (!in_rx_event) 153 | NVIC_ENABLE_IRQ(IRQ_USB1); 154 | 155 | return count; 156 | } 157 | 158 | // Function used to send packets out of the TX endpoint 159 | // This is used to send button reports 160 | int usb_xinput_send(const void *_buffer, uint8_t nbytes) 161 | { 162 | if (nbytes > TX_BUFSIZE) return -1; 163 | if (!usb_configuration) return -1; 164 | uint32_t head = tx_head; 165 | transfer_t *xfer = tx_transfer + head; 166 | uint32_t wait_begin_at = systick_millis_count; 167 | while (1) { 168 | uint32_t status = usb_transfer_status(xfer); 169 | if (!(status & 0x80)) { 170 | if (status & 0x68) { 171 | // TODO: what if status has errors??? 172 | //printf("ERROR status = %x, i=%d, ms=%u\n", 173 | // status, tx_head, systick_millis_count); 174 | } 175 | transmit_previous_timeout = 0; 176 | break; 177 | } 178 | if (transmit_previous_timeout) return -1; 179 | if (systick_millis_count - wait_begin_at > TX_TIMEOUT_MSEC) { 180 | // waited too long, assume the USB host isn't listening 181 | transmit_previous_timeout = 1; 182 | return -1; 183 | } 184 | if (!usb_configuration) return -1; 185 | yield(); 186 | } 187 | delayNanoseconds(30); // TODO: why is status ready too soon? 188 | uint8_t *buffer = txbuffer + head * TX_BUFSIZE; 189 | memcpy(buffer, _buffer, nbytes); 190 | usb_prepare_transfer(xfer, buffer, nbytes, 0); 191 | arm_dcache_flush_delete(buffer, TX_BUFSIZE); 192 | usb_transmit(XINPUT_TX_ENDPOINT, xfer); 193 | if (++head >= TX_NUM) head = 0; 194 | tx_head = head; 195 | return 0; 196 | } 197 | 198 | #endif // XINPUT_INTERFACE 199 | -------------------------------------------------------------------------------- /teensy/avr/cores/teensy4/usb_xinput.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016 Zachery Littell 4 | * Modified (c) 2019 David Madison 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef USBxinput_h_ 26 | #define USBxinput_h_ 27 | 28 | #include "usb_desc.h" 29 | 30 | #if defined(XINPUT_INTERFACE) 31 | 32 | #include 33 | #include 34 | 35 | // C language implementation 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | void usb_xinput_configure(); 40 | bool usb_xinput_connected(void); 41 | uint16_t usb_xinput_available(void); 42 | int usb_xinput_send(const void *buffer, uint8_t nbytes); 43 | int usb_xinput_recv(void *buffer, uint8_t nbytes); 44 | extern void (*usb_xinput_recv_callback)(void); 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | 50 | // C++ interface 51 | #ifdef __cplusplus 52 | class XInputUSB 53 | { 54 | public: 55 | static bool connected(void) { return usb_xinput_connected(); } 56 | static uint16_t available(void) { return usb_xinput_available(); } 57 | static int send(const void *buffer, uint8_t nbytes) { return usb_xinput_send(buffer, nbytes); } 58 | static int recv(void *buffer, uint8_t nbytes) { return usb_xinput_recv(buffer, nbytes); } 59 | static void setRecvCallback(void (*callback)(void)) { usb_xinput_recv_callback = callback; } 60 | }; 61 | 62 | #endif // __cplusplus 63 | 64 | #endif // XINPUT_INTERFACE 65 | 66 | #endif // USBxinput_h_ 67 | --------------------------------------------------------------------------------