├── README.md
├── demos
├── console
│ ├── console.js
│ ├── hterm_all.js
│ ├── index.html
│ └── sketch
│ │ └── sketch.ino
├── index.html
├── rgb
│ ├── index.html
│ ├── rgb.js
│ └── sketch
│ │ └── sketch.ino
└── serial.js
├── hardware
└── webusb
│ └── avr
│ ├── boards.txt
│ └── platform.txt
└── library
└── WebUSB
├── WebUSB.cpp
├── WebUSB.h
├── keywords.txt
└── library.properties
/README.md:
--------------------------------------------------------------------------------
1 | WebUSB ❤ ️Arduino
2 | ================
3 |
4 | This repository contains an Arduino library for WebUSB-enabling your sketches.
5 | Example sketches and JavaScript code are available in the demos directory.
6 |
7 | The WebUSB object is a copy of the Arduino SDK's built-in USB serial library.
8 | It creates a WebUSB-compatible vendor-specific interface rather than one marked
9 | as USB CDC-ACM. This prevents operating system drivers from claiming the device
10 | and making it inaccessible to the browser. This library also implements:
11 |
12 | * The WebUSB landing page descriptor, providing a hint to the browser about
13 | what page the user should navigate to to interact with the device. In
14 | Google Chrome the presence of this descriptor causes the browser to display
15 | a notification when the device is connected. The user can click on this
16 | notification to navigate directly to the provided URL.
17 | * Microsoft OS 2.0 Descriptors which instruct the Windows operating system
18 | (8.1 and above) to automatically the `WinUSB.sys` driver so that the browser
19 | can connect to the device.
20 |
21 | Compatible Hardware
22 | -------------------
23 |
24 | WebUSB requires an Arduino model that gives the sketch complete control over the USB hardware. This library has been tested with the following models:
25 |
26 | * Arduino Leonardo
27 | * Arduino/Genuino Micro
28 | * Arduino/Genuino Zero
29 | * Arduino/Genuino MKR1000
30 | * Arduino MKRZero
31 | * Arduino MKR FOX 1200
32 | * Arduino MKR WAN 1300
33 | * Arduino MKR GSM 1400
34 | * Arduino MKR NB 1500
35 | * Arduino MKR WiFi 1010
36 | * Arduino MKR Vidor 4000
37 | * Arduino NANO 33 IoT
38 | * Adafruit Feather 32u4
39 | * Adafruit ItsyBitsy 32u4
40 | * Adafruit Feather M0 Express
41 |
42 | Getting Started
43 | ---------------
44 |
45 | 1. Install at least version 1.6.11 of the [Arduino IDE](https://www.arduino.cc/en/Main/Software).
46 |
47 | 2. The WebUSB library provides all the extra low-level USB code necessary for WebUSB support except for one thing: Your device must be upgraded from USB 2.0 to USB 2.1. To do this go into the SDK installation directory and open `hardware/arduino/avr/cores/arduino/USBCore.h`. Then find the line `#define USB_VERSION 0x200` and change `0x200` to `0x210`. That's it!
48 |
49 | **macOS:** Right click on the Arduino application icon and then click on show package contents menu item. Navigate to `Contents/Java/hardware/arduino/avr/cores/arduino/USBCore.h`
50 |
51 | **Warning:** Windows requires USB 2.1 devices to present a Binary Object Store (BOS) descriptor when they are enumerated. The code to support this is added by including the "WebUSB" library in your sketch. If you do not include this library after making this change to the SDK then Windows will no longer be able to recognize your device and you will not be able to upload new sketches to it.
52 |
53 | 3. Copy (or symlink) the `library/WebUSB` directory from this repository into the `libraries` folder in your sketchbooks directory.
54 |
55 | 4. Launch the Arduino IDE. You should see "WebUSB" as an option under "Sketch > Include Library".
56 |
57 | 5. Load up `demos/rgb/sketch/sketch.ino` and program it to your device.
58 |
59 | 6. When the sketch is finished uploading you should see a notification from Chrome: "Go to [https://webusb.github.io/arduino/demos/](https://webusb.github.io/arduino/demos/) to connect." Try it out!
60 |
61 | **Windows:** This notification is currently disabled in Chrome on Windows due to [Chromium issue 656702](https://crbug.com/656702). Implementation of new, more stable USB support for Windows is tracked on Chromium issues [422562](https://crbug.com/422562) and [637404](https://crbug.com/637404).
62 |
63 | **Android:** This notification is not supported on Android because of OS
64 | limitations that prevent the browser from connecting to a device without user
65 | interaction.
66 |
67 | Adding New Boards of Supported Architecture
68 | -------------------------------------------
69 | 1. Plug in your board.
70 | 2. Run `lsusb` and find your boards _vendor ID_ and _product ID_
71 | Example: `Bus 001 Device 119: ID 2341:805a Arduino SA` where 0x2341 is _vendor ID_ and 0x805a is _product ID_.
72 | 3. Add your board's _vendor ID_ and _product ID_ to the `filters` in `serial.js` file -
73 | ```
74 | const filters = [
75 | { 'vendorId': 0x2341, 'productId': 0x8036 }, // Arduino Leonardo
76 | { 'vendorId': 0x2341, 'productId': 0x8037 }, // Arduino Micro
77 | { 'vendorId': 0x2341, 'productId': 0x804d }, // Arduino/Genuino Zero
78 | { 'vendorId': 0x2341, 'productId': 0x804e }, // Arduino/Genuino MKR1000
79 | { 'vendorId': 0x2341, 'productId': 0x804f }, // Arduino MKRZERO
80 | { 'vendorId': 0x2341, 'productId': 0x8050 }, // Arduino MKR FOX 1200
81 | { 'vendorId': 0x2341, 'productId': 0x8052 }, // Arduino MKR GSM 1400
82 | { 'vendorId': 0x2341, 'productId': 0x8053 }, // Arduino MKR WAN 1300
83 | { 'vendorId': 0x2341, 'productId': 0x8054 }, // Arduino MKR WiFi 1010
84 | { 'vendorId': 0x2341, 'productId': 0x8055 }, // Arduino MKR NB 1500
85 | { 'vendorId': 0x2341, 'productId': 0x8056 }, // Arduino MKR Vidor 4000
86 | { 'vendorId': 0x2341, 'productId': 0x8057 }, // Arduino NANO 33 IoT
87 | { 'vendorId': 0x239A, 'productId': 0x000E }, // Adafruit ItsyBitsy 32u4
88 | { 'vendorId': 0x239A, 'productId': 0x800D }, // Adafruit ItsyBitsy 32u4
89 | ];
90 | ```
91 | 4. Try connecting !
92 |
93 | OR
94 |
95 | 1. Connect your board
96 | 2. Load the sketch onto your board
97 | 3. Open the landing URL
98 | 4. Inspect the page and goto _Sources_
99 | 5. Open `serial.js` in the inspector and add your _vendor ID_ and _product ID_ and don't forget to save - press `Ctrl+S`
100 | 6. Press Connect and hopefully it works!
--------------------------------------------------------------------------------
/demos/console/console.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | hterm.defaultStorage = new lib.Storage.Local();
5 |
6 | var port;
7 |
8 | let textEncoder = new TextEncoder();
9 |
10 | let t = new hterm.Terminal();
11 | t.onTerminalReady = () => {
12 | console.log('Terminal ready.');
13 | let io = t.io.push();
14 |
15 | io.onVTKeystroke = str => {
16 | if (port !== undefined) {
17 | port.send(textEncoder.encode(str)).catch(error => {
18 | t.io.println('Send error: ' + error);
19 | });
20 | }
21 | };
22 |
23 | io.sendString = str => {
24 | if (port !== undefined) {
25 | port.send(textEncoder.encode(str)).catch(error => {
26 | t.io.println('Send error: ' + error);
27 | });
28 | }
29 | };
30 | };
31 |
32 | document.addEventListener('DOMContentLoaded', event => {
33 | let connectButton = document.querySelector('#connect');
34 |
35 | t.decorate(document.querySelector('#terminal'));
36 | t.setWidth(80);
37 | t.setHeight(24);
38 | t.installKeyboard();
39 |
40 | function connect() {
41 | t.io.println('Connecting to ' + port.device_.productName + '...');
42 | port.connect().then(() => {
43 | console.log(port);
44 | t.io.println('Connected.');
45 | connectButton.textContent = 'Disconnect';
46 | port.onReceive = data => {
47 | let textDecoder = new TextDecoder();
48 | t.io.print(textDecoder.decode(data));
49 | }
50 | port.onReceiveError = error => {
51 | t.io.println('Receive error: ' + error);
52 | };
53 | }, error => {
54 | t.io.println('Connection error: ' + error);
55 | });
56 | };
57 |
58 | connectButton.addEventListener('click', function() {
59 | if (port) {
60 | port.disconnect();
61 | connectButton.textContent = 'Connect';
62 | port = null;
63 | } else {
64 | serial.requestPort().then(selectedPort => {
65 | port = selectedPort;
66 | connect();
67 | }).catch(error => {
68 | t.io.println('Connection error: ' + error);
69 | });
70 | }
71 | });
72 |
73 | serial.getPorts().then(ports => {
74 | if (ports.length == 0) {
75 | t.io.println('No devices found.');
76 | } else {
77 | port = ports[0];
78 | connect();
79 | }
80 | });
81 | });
82 | })();
83 |
--------------------------------------------------------------------------------
/demos/console/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Console
7 |
8 |
9 |
10 |
11 |
12 |
13 | Connect
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/demos/console/sketch/sketch.ino:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /**
4 | * Creating an instance of WebUSBSerial will add an additional USB interface to
5 | * the device that is marked as vendor-specific (rather than USB CDC-ACM) and
6 | * is therefore accessible to the browser.
7 | *
8 | * The URL here provides a hint to the browser about what page the user should
9 | * navigate to to interact with the device.
10 | */
11 | WebUSB WebUSBSerial(1 /* https:// */, "webusb.github.io/arduino/demos/console");
12 |
13 | #define Serial WebUSBSerial
14 |
15 | const int ledPin = 13;
16 |
17 | void setup() {
18 | while (!Serial) {
19 | ;
20 | }
21 | Serial.begin(9600);
22 | Serial.write("Sketch begins.\r\n> ");
23 | Serial.flush();
24 | pinMode(ledPin, OUTPUT);
25 | }
26 |
27 | void loop() {
28 | if (Serial && Serial.available()) {
29 | int byte = Serial.read();
30 | Serial.write(byte);
31 | if (byte == 'H') {
32 | Serial.write("\r\nTurning LED on.");
33 | digitalWrite(ledPin, HIGH);
34 | } else if (byte == 'L') {
35 | Serial.write("\r\nTurning LED off.");
36 | digitalWrite(ledPin, LOW);
37 | }
38 | Serial.write("\r\n> ");
39 | Serial.flush();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/demos/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WebUSB Demos
5 |
6 |
7 | WebUSB Demos
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/demos/rgb/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | RGB LED
7 |
8 |
9 |
10 |
11 |
12 | Connect
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/demos/rgb/rgb.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | document.addEventListener('DOMContentLoaded', event => {
5 | let connectButton = document.querySelector("#connect");
6 | let statusDisplay = document.querySelector('#status');
7 | let redSlider = document.querySelector('#red');
8 | let greenSlider = document.querySelector('#green');
9 | let blueSlider = document.querySelector('#blue');
10 | let port;
11 |
12 | function connect() {
13 | port.connect().then(() => {
14 | statusDisplay.textContent = '';
15 | connectButton.textContent = 'Disconnect';
16 |
17 | port.onReceive = data => {
18 | let textDecoder = new TextDecoder();
19 | console.log(textDecoder.decode(data));
20 | }
21 | port.onReceiveError = error => {
22 | console.error(error);
23 | };
24 | }, error => {
25 | statusDisplay.textContent = error;
26 | });
27 | }
28 |
29 | function onUpdate() {
30 | if (!port) {
31 | return;
32 | }
33 |
34 | let view = new Uint8Array(3);
35 | view[0] = parseInt(redSlider.value);
36 | view[1] = parseInt(greenSlider.value);
37 | view[2] = parseInt(blueSlider.value);
38 | port.send(view);
39 | };
40 |
41 | redSlider.addEventListener('input', onUpdate);
42 | greenSlider.addEventListener('input', onUpdate);
43 | blueSlider.addEventListener('input', onUpdate);
44 |
45 | connectButton.addEventListener('click', function() {
46 | if (port) {
47 | port.disconnect();
48 | connectButton.textContent = 'Connect';
49 | statusDisplay.textContent = '';
50 | port = null;
51 | } else {
52 | serial.requestPort().then(selectedPort => {
53 | port = selectedPort;
54 | connect();
55 | }).catch(error => {
56 | statusDisplay.textContent = error;
57 | });
58 | }
59 | });
60 |
61 | serial.getPorts().then(ports => {
62 | if (ports.length == 0) {
63 | statusDisplay.textContent = 'No device found.';
64 | } else {
65 | statusDisplay.textContent = 'Connecting...';
66 | port = ports[0];
67 | connect();
68 | }
69 | });
70 | });
71 | })();
72 |
--------------------------------------------------------------------------------
/demos/rgb/sketch/sketch.ino:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /**
4 | * Creating an instance of WebUSBSerial will add an additional USB interface to
5 | * the device that is marked as vendor-specific (rather than USB CDC-ACM) and
6 | * is therefore accessible to the browser.
7 | *
8 | * The URL here provides a hint to the browser about what page the user should
9 | * navigate to to interact with the device.
10 | */
11 | WebUSB WebUSBSerial(1 /* https:// */, "webusb.github.io/arduino/demos/rgb");
12 |
13 | #define Serial WebUSBSerial
14 |
15 | const int redPin = 9;
16 | const int greenPin = 10;
17 | const int bluePin = 11;
18 | int color[3];
19 | int colorIndex;
20 |
21 | void setup() {
22 | while (!Serial) {
23 | ;
24 | }
25 | Serial.begin(9600);
26 | Serial.write("Sketch begins.\r\n");
27 | Serial.flush();
28 | colorIndex = 0;
29 | }
30 |
31 | void loop() {
32 | if (Serial && Serial.available()) {
33 | color[colorIndex++] = Serial.read();
34 | if (colorIndex == 3) {
35 | analogWrite(redPin, color[0]);
36 | analogWrite(greenPin, color[1]);
37 | analogWrite(bluePin, color[2]);
38 | Serial.print("Set LED to ");
39 | Serial.print(color[0]);
40 | Serial.print(", ");
41 | Serial.print(color[1]);
42 | Serial.print(", ");
43 | Serial.print(color[2]);
44 | Serial.print(".\r\n");
45 | Serial.flush();
46 | colorIndex = 0;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/demos/serial.js:
--------------------------------------------------------------------------------
1 | var serial = {};
2 |
3 | (function() {
4 | 'use strict';
5 |
6 | serial.getPorts = function() {
7 | return navigator.usb.getDevices().then(devices => {
8 | return devices.map(device => new serial.Port(device));
9 | });
10 | };
11 |
12 | serial.requestPort = function() {
13 | const filters = [
14 | { 'vendorId': 0x2341, 'productId': 0x8036 }, // Arduino Leonardo
15 | { 'vendorId': 0x2341, 'productId': 0x8037 }, // Arduino Micro
16 | { 'vendorId': 0x2341, 'productId': 0x804d }, // Arduino/Genuino Zero
17 | { 'vendorId': 0x2341, 'productId': 0x804e }, // Arduino/Genuino MKR1000
18 | { 'vendorId': 0x2341, 'productId': 0x804f }, // Arduino MKRZERO
19 | { 'vendorId': 0x2341, 'productId': 0x8050 }, // Arduino MKR FOX 1200
20 | { 'vendorId': 0x2341, 'productId': 0x8052 }, // Arduino MKR GSM 1400
21 | { 'vendorId': 0x2341, 'productId': 0x8053 }, // Arduino MKR WAN 1300
22 | { 'vendorId': 0x2341, 'productId': 0x8054 }, // Arduino MKR WiFi 1010
23 | { 'vendorId': 0x2341, 'productId': 0x8055 }, // Arduino MKR NB 1500
24 | { 'vendorId': 0x2341, 'productId': 0x8056 }, // Arduino MKR Vidor 4000
25 | { 'vendorId': 0x2341, 'productId': 0x8057 }, // Arduino NANO 33 IoT
26 | { 'vendorId': 0x239A }, // Adafruit Boards!
27 | ];
28 | return navigator.usb.requestDevice({ 'filters': filters }).then(
29 | device => new serial.Port(device)
30 | );
31 | }
32 |
33 | serial.Port = function(device) {
34 | this.device_ = device;
35 | this.interfaceNumber_ = 2; // original interface number of WebUSB Arduino demo
36 | this.endpointIn_ = 5; // original in endpoint ID of WebUSB Arduino demo
37 | this.endpointOut_ = 4; // original out endpoint ID of WebUSB Arduino demo
38 | };
39 |
40 | serial.Port.prototype.connect = function() {
41 | let readLoop = () => {
42 | this.device_.transferIn(this.endpointIn_, 64).then(result => {
43 | this.onReceive(result.data);
44 | readLoop();
45 | }, error => {
46 | this.onReceiveError(error);
47 | });
48 | };
49 |
50 | return this.device_.open()
51 | .then(() => {
52 | if (this.device_.configuration === null) {
53 | return this.device_.selectConfiguration(1);
54 | }
55 | })
56 | .then(() => {
57 | var configurationInterfaces = this.device_.configuration.interfaces;
58 | configurationInterfaces.forEach(element => {
59 | element.alternates.forEach(elementalt => {
60 | if (elementalt.interfaceClass==0xff) {
61 | this.interfaceNumber_ = element.interfaceNumber;
62 | elementalt.endpoints.forEach(elementendpoint => {
63 | if (elementendpoint.direction == "out") {
64 | this.endpointOut_ = elementendpoint.endpointNumber;
65 | }
66 | if (elementendpoint.direction=="in") {
67 | this.endpointIn_ =elementendpoint.endpointNumber;
68 | }
69 | })
70 | }
71 | })
72 | })
73 | })
74 | .then(() => this.device_.claimInterface(this.interfaceNumber_))
75 | .then(() => this.device_.selectAlternateInterface(this.interfaceNumber_, 0))
76 | // The vendor-specific interface provided by a device using this
77 | // Arduino library is a copy of the normal Arduino USB CDC-ACM
78 | // interface implementation and so reuses some requests defined by
79 | // that specification. This request sets the DTR (data terminal
80 | // ready) signal high to indicate to the device that the host is
81 | // ready to send and receive data.
82 | .then(() => this.device_.controlTransferOut({
83 | 'requestType': 'class',
84 | 'recipient': 'interface',
85 | 'request': 0x22,
86 | 'value': 0x01,
87 | 'index': this.interfaceNumber_}))
88 | .then(() => {
89 | readLoop();
90 | });
91 | };
92 |
93 | serial.Port.prototype.disconnect = function() {
94 | // This request sets the DTR (data terminal ready) signal low to
95 | // indicate to the device that the host has disconnected.
96 | return this.device_.controlTransferOut({
97 | 'requestType': 'class',
98 | 'recipient': 'interface',
99 | 'request': 0x22,
100 | 'value': 0x00,
101 | 'index': this.interfaceNumber_})
102 | .then(() => this.device_.close());
103 | };
104 |
105 | serial.Port.prototype.send = function(data) {
106 | return this.device_.transferOut(this.endpointOut_, data);
107 | };
108 | })();
109 |
--------------------------------------------------------------------------------
/hardware/webusb/avr/boards.txt:
--------------------------------------------------------------------------------
1 | microwebusb.name=Arduino Micro (WebUSB)
2 |
3 | microwebusb.upload.tool=arduino:avrdude
4 | microwebusb.upload.protocol=avr109
5 | microwebusb.upload.maximum_size=28672
6 | microwebusb.upload.maximum_data_size=2560
7 | microwebusb.upload.speed=57600
8 | microwebusb.upload.disable_flushing=true
9 | microwebusb.upload.use_1200bps_touch=true
10 | microwebusb.upload.wait_for_upload_port=true
11 |
12 | microwebusb.bootloader.tool=arduino:avrdude
13 | microwebusb.bootloader.low_fuses=0xff
14 | microwebusb.bootloader.high_fuses=0xd8
15 | microwebusb.bootloader.extended_fuses=0xcb
16 | microwebusb.bootloader.file=caterina/Caterina2-Micro-WebUSB.hex
17 | microwebusb.bootloader.unlock_bits=0x3F
18 | microwebusb.bootloader.lock_bits=0x2F
19 |
20 | microwebusb.build.mcu=atmega32u4
21 | microwebusb.build.f_cpu=16000000L
22 | microwebusb.build.vid=0x2341
23 | microwebusb.build.pid=0x8037
24 | microwebusb.build.usb_product="Arduino Micro WebUSB"
25 | microwebusb.build.board=AVR_MICRO
26 | microwebusb.build.core=arduino:arduino
27 | microwebusb.build.variant=arduino:micro
28 | microwebusb.build.extra_flags={build.usb_flags} "-DUSB_VERSION=0x210"
29 |
30 | leowebusb.name=Arduino Leonardo (WebUSB)
31 |
32 | leowebusb.upload.tool=arduino:avrdude
33 | leowebusb.upload.protocol=avr109
34 | leowebusb.upload.maximum_size=28672
35 | leowebusb.upload.maximum_data_size=2560
36 | leowebusb.upload.speed=57600
37 | leowebusb.upload.disable_flushing=true
38 | leowebusb.upload.use_1200bps_touch=true
39 | leowebusb.upload.wait_for_upload_port=true
40 |
41 | leowebusb.bootloader.tool=arduino:avrdude
42 | leowebusb.bootloader.low_fuses=0xff
43 | leowebusb.bootloader.high_fuses=0xd8
44 | leowebusb.bootloader.extended_fuses=0xcb
45 | leowebusb.bootloader.file=caterina/Caterina2-Leonardo-WebUSB.hex
46 | leowebusb.bootloader.unlock_bits=0x3F
47 | leowebusb.bootloader.lock_bits=0x2F
48 |
49 | leowebusb.build.mcu=atmega32u4
50 | leowebusb.build.f_cpu=16000000L
51 | leowebusb.build.vid=0x2341
52 | leowebusb.build.pid=0x8036
53 | leowebusb.build.usb_product="Arduino Leonardo WebUSB"
54 | leowebusb.build.board=AVR_LEONARDO
55 | leowebusb.build.core=arduino:arduino
56 | leowebusb.build.variant=arduino:leonardo
57 | leowebusb.build.extra_flags={build.usb_flags} "-DUSB_VERSION=0x210"
58 |
59 |
--------------------------------------------------------------------------------
/hardware/webusb/avr/platform.txt:
--------------------------------------------------------------------------------
1 | name=Arduino AVR Boards (WebUSB version)
2 | version=1.0.0
3 |
4 |
--------------------------------------------------------------------------------
/library/WebUSB/WebUSB.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2015, Arduino LLC
3 | Original code (pre-library): Copyright (c) 2011, Peter Barrett
4 |
5 | Permission to use, copy, modify, and/or distribute this software for
6 | any purpose with or without fee is hereby granted, provided that the
7 | above copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 | SOFTWARE.
17 | */
18 |
19 | #define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00
20 | #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01
21 | #define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02
22 | #define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03
23 | #define MS_OS_20_FEATURE_REG_PROPERTY 0x04
24 | #define MS_OS_20_DESCRIPTOR_LENGTH 0xb2
25 |
26 | #include "WebUSB.h"
27 |
28 | #ifdef ARDUINO_ARCH_SAMD
29 |
30 | #define USB_SendControl USBDevice.sendControl
31 | #define USB_RecvControl USBDevice.recvControl
32 | #define USB_Available USBDevice.available
33 | #define USB_Recv USBDevice.recv
34 | #define USB_Send USBDevice.send
35 | #define USB_SendSpace(ep) (EPX_SIZE - 1)
36 | #define USB_Flush USBDevice.flush
37 |
38 | #define TRANSFER_PGM 0
39 |
40 | #define EP_TYPE_BULK_IN_WEBUSB USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0);
41 | #define EP_TYPE_BULK_OUT_WEBUSB USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0);
42 |
43 | #else
44 |
45 | #define EP_TYPE_BULK_IN_WEBUSB EP_TYPE_BULK_IN
46 | #define EP_TYPE_BULK_OUT_WEBUSB EP_TYPE_BULK_OUT
47 |
48 | #endif
49 |
50 | const uint8_t BOS_DESCRIPTOR_PREFIX[] PROGMEM = {
51 | 0x05, // Length
52 | 0x0F, // Binary Object Store descriptor
53 | 0x39, 0x00, // Total length
54 | 0x02, // Number of device capabilities
55 |
56 | // WebUSB Platform Capability descriptor (bVendorCode == 0x01).
57 | 0x18, // Length
58 | 0x10, // Device Capability descriptor
59 | 0x05, // Platform Capability descriptor
60 | 0x00, // Reserved
61 | 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,
62 | 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, // WebUSB GUID
63 | 0x00, 0x01, // Version 1.0
64 | 0x01, // Vendor request code
65 | };
66 |
67 | // Landing page (1 byte) sent in the middle.
68 |
69 | const uint8_t BOS_DESCRIPTOR_SUFFIX[] PROGMEM {
70 | // Microsoft OS 2.0 Platform Capability Descriptor (MS_VendorCode == 0x02)
71 | 0x1C, // Length
72 | 0x10, // Device Capability descriptor
73 | 0x05, // Platform Capability descriptor
74 | 0x00, // Reserved
75 | 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C,
76 | 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, // MS OS 2.0 GUID
77 | 0x00, 0x00, 0x03, 0x06, // Windows version
78 | MS_OS_20_DESCRIPTOR_LENGTH, 0x00, // Descriptor set length
79 | 0x02, // Vendor request code
80 | 0x00 // Alternate enumeration code
81 | };
82 |
83 | const uint8_t MS_OS_20_DESCRIPTOR_PREFIX[] PROGMEM = {
84 | // Microsoft OS 2.0 descriptor set header (table 10)
85 | 0x0A, 0x00, // Descriptor size (10 bytes)
86 | MS_OS_20_SET_HEADER_DESCRIPTOR, 0x00, // MS OS 2.0 descriptor set header
87 | 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
88 | MS_OS_20_DESCRIPTOR_LENGTH, 0x00, // Size, MS OS 2.0 descriptor set
89 |
90 | // Microsoft OS 2.0 configuration subset header
91 | 0x08, 0x00, // Descriptor size (8 bytes)
92 | MS_OS_20_SUBSET_HEADER_CONFIGURATION, 0x00, // MS OS 2.0 configuration subset header
93 | 0x00, // bConfigurationValue
94 | 0x00, // Reserved
95 | 0xA8, 0x00, // Size, MS OS 2.0 configuration subset
96 |
97 | // Microsoft OS 2.0 function subset header
98 | 0x08, 0x00, // Descriptor size (8 bytes)
99 | MS_OS_20_SUBSET_HEADER_FUNCTION, 0x00, // MS OS 2.0 function subset header
100 | };
101 |
102 | // First interface number (1 byte) sent here.
103 |
104 | const uint8_t MS_OS_20_DESCRIPTOR_SUFFIX[] PROGMEM = {
105 | 0x00, // Reserved
106 | 0xA0, 0x00, // Size, MS OS 2.0 function subset
107 |
108 | // Microsoft OS 2.0 compatible ID descriptor (table 13)
109 | 0x14, 0x00, // wLength
110 | MS_OS_20_FEATURE_COMPATIBLE_ID, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
111 | 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 | };
114 |
115 |
116 | const uint8_t MS_OS_20_CUSTOM_PROPERTY[] PROGMEM = {
117 | 0x84, 0x00, //wLength:
118 | MS_OS_20_FEATURE_REG_PROPERTY, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9)
119 | 0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15)
120 | 0x2a, 0x00, //wPropertyNameLength:
121 | //bPropertyName: “DeviceInterfaceGUID”
122 | 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
123 | 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00,
124 | 0x00, 0x00,
125 | 0x50, 0x00, // wPropertyDataLength
126 | //bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
127 | '{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00,
128 | '0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
129 | '8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
130 | '8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
131 | };
132 |
133 | typedef struct
134 | {
135 | uint32_t dwDTERate;
136 | uint8_t bCharFormat;
137 | uint8_t bParityType;
138 | uint8_t bDataBits;
139 | uint8_t lineState;
140 | } LineInfo;
141 |
142 | static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
143 | static volatile int32_t breakValue = -1;
144 |
145 | int WebUSB::getInterface(uint8_t* interfaceCount)
146 | {
147 | *interfaceCount += 1; // uses 1 interface
148 | WebUSBDescriptor webUSBInterface = {
149 | D_INTERFACE(pluggedInterface, 2, 0xff, 0, 0),
150 | D_ENDPOINT(USB_ENDPOINT_OUT(pluggedEndpoint),USB_ENDPOINT_TYPE_BULK,0x40,0),
151 | D_ENDPOINT(USB_ENDPOINT_IN (pluggedEndpoint+1),USB_ENDPOINT_TYPE_BULK,0x40,0)
152 | };
153 | return USB_SendControl(0, &webUSBInterface, sizeof(webUSBInterface));
154 | }
155 |
156 | int WebUSB::getDescriptor(USBSetup& setup)
157 | {
158 | if (USB_BOS_DESCRIPTOR_TYPE == setup.wValueH)
159 | {
160 | if (setup.wValueL == 0 && setup.wIndex == 0) {
161 | if (USB_SendControl(TRANSFER_PGM, &BOS_DESCRIPTOR_PREFIX, sizeof(BOS_DESCRIPTOR_PREFIX)) < 0)
162 | return -1;
163 | uint8_t landingPage = landingPageUrl ? 1 : 0;
164 | if (USB_SendControl(0, &landingPage, 1) < 0)
165 | return -1;
166 | if (USB_SendControl(TRANSFER_PGM, &BOS_DESCRIPTOR_SUFFIX, sizeof(BOS_DESCRIPTOR_SUFFIX)) < 0)
167 | return -1;
168 | return sizeof(BOS_DESCRIPTOR_PREFIX) + 1 + sizeof(BOS_DESCRIPTOR_SUFFIX);
169 | }
170 | }
171 | return 0;
172 | }
173 |
174 | uint8_t WebUSB::getShortName(char* name)
175 | {
176 | uint8_t len = strlen(shortName);
177 | memcpy(name, shortName, len);
178 | return len;
179 | }
180 |
181 | bool WebUSB::VendorControlRequest(USBSetup& setup)
182 | {
183 | if (setup.bmRequestType == (REQUEST_DEVICETOHOST | REQUEST_VENDOR | REQUEST_DEVICE)) {
184 | if (setup.bRequest == 0x01 && setup.wIndex == WEBUSB_REQUEST_GET_URL && landingPageUrl)
185 | {
186 | if (setup.wValueL != 1)
187 | return false;
188 | uint8_t urlLength = strlen(landingPageUrl);
189 | uint8_t descriptorLength = urlLength + 3;
190 | if (USB_SendControl(0, &descriptorLength, 1) < 0)
191 | return false;
192 | uint8_t descriptorType = 3;
193 | if (USB_SendControl(0, &descriptorType, 1) < 0)
194 | return false;
195 | if (USB_SendControl(0, &landingPageScheme, 1) < 0)
196 | return false;
197 | return USB_SendControl(0, landingPageUrl, urlLength) >= 0;
198 | }
199 | else if (setup.bRequest == 0x02 && setup.wIndex == MS_OS_20_REQUEST_DESCRIPTOR)
200 | {
201 | if (USB_SendControl(TRANSFER_PGM, &MS_OS_20_DESCRIPTOR_PREFIX, sizeof(MS_OS_20_DESCRIPTOR_PREFIX)) < 0)
202 | return false;
203 | if (USB_SendControl(0, &pluggedInterface, 1) < 0)
204 | return false;
205 | if (USB_SendControl(TRANSFER_PGM, &MS_OS_20_DESCRIPTOR_SUFFIX, sizeof(MS_OS_20_DESCRIPTOR_SUFFIX)) < 0)
206 | return false;
207 | if (USB_SendControl(TRANSFER_PGM, &MS_OS_20_CUSTOM_PROPERTY, sizeof(MS_OS_20_CUSTOM_PROPERTY)) < 0)
208 | return false;
209 | return true;
210 | }
211 | }
212 | return false;
213 | }
214 |
215 |
216 | bool WebUSB::setup(USBSetup& setup)
217 | {
218 | uint8_t r = setup.bRequest;
219 | uint8_t requestType = setup.bmRequestType;
220 |
221 | if (REQUEST_CLASS == (requestType & REQUEST_TYPE) && (pluggedInterface == setup.wIndex)) {
222 | if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
223 | {
224 | if (CDC_GET_LINE_CODING == r)
225 | {
226 | return USB_SendControl(0,(void*)&_usbLineInfo,7) >= 0;
227 | }
228 | }
229 |
230 | if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
231 | {
232 | if (CDC_SEND_BREAK == r)
233 | {
234 | breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
235 | }
236 |
237 | if (CDC_SET_LINE_CODING == r)
238 | {
239 | USB_RecvControl((void*)&_usbLineInfo,7);
240 | }
241 |
242 | if (CDC_SET_CONTROL_LINE_STATE == r)
243 | {
244 | _usbLineInfo.lineState = setup.wValueL;
245 | }
246 | return true;
247 | }
248 | } else if (REQUEST_VENDOR == (requestType & REQUEST_TYPE)) {
249 | return VendorControlRequest(setup);
250 | }
251 | return false;
252 | }
253 |
254 | WebUSB::WebUSB(uint8_t landingPageScheme, const char* landingPageUrl)
255 | : PluggableUSBModule(2, 1, epType),
256 | landingPageScheme(landingPageScheme), landingPageUrl(landingPageUrl),
257 | shortName(WEBUSB_SHORT_NAME)
258 | {
259 | // one interface, 2 endpoints
260 | epType[0] = EP_TYPE_BULK_OUT_WEBUSB;
261 | epType[1] = EP_TYPE_BULK_IN_WEBUSB;
262 | PluggableUSB().plug(this);
263 | }
264 |
265 | void WebUSB::begin(unsigned long /* baud_count */)
266 | {
267 | peek_buffer = -1;
268 | }
269 |
270 | void WebUSB::begin(unsigned long /* baud_count */, byte /* config */)
271 | {
272 | peek_buffer = -1;
273 | }
274 |
275 | void WebUSB::end(void)
276 | {
277 | }
278 |
279 | void WebUSB::setShortName(const char* name)
280 | {
281 | shortName = name;
282 | }
283 |
284 | int WebUSB::available(void)
285 | {
286 | if (peek_buffer >= 0) {
287 | return 1 + USB_Available(pluggedEndpoint);
288 | }
289 | return USB_Available(pluggedEndpoint);
290 | }
291 |
292 | int WebUSB::peek(void)
293 | {
294 | if (peek_buffer < 0)
295 | peek_buffer = USB_Recv(pluggedEndpoint);
296 | return peek_buffer;
297 | }
298 |
299 | int WebUSB::read(void)
300 | {
301 | if (peek_buffer >= 0) {
302 | int c = peek_buffer;
303 | peek_buffer = -1;
304 | return c;
305 | }
306 | return USB_Recv(pluggedEndpoint);
307 | }
308 |
309 | int WebUSB::availableForWrite(void)
310 | {
311 | return USB_SendSpace(pluggedEndpoint+1);
312 | }
313 |
314 | void WebUSB::flush(void)
315 | {
316 | USB_Flush(pluggedEndpoint+1);
317 | }
318 |
319 | size_t WebUSB::write(uint8_t c)
320 | {
321 | return write(&c, 1);
322 | }
323 |
324 | size_t WebUSB::write(const uint8_t *buffer, size_t size)
325 | {
326 | /* only try to send bytes if the high-level CDC connection itself
327 | is open (not just the pipe) - the OS should set lineState when the port
328 | is opened and clear lineState when the port is closed.
329 | bytes sent before the user opens the connection or after
330 | the connection is closed are lost - just like with a UART. */
331 |
332 | // TODO - ZE - check behavior on different OSes and test what happens if an
333 | // open connection isn't broken cleanly (cable is yanked out, host dies
334 | // or locks up, or host virtual serial port hangs)
335 | if (this) {
336 | int r = USB_Send(pluggedEndpoint+1,buffer,size);
337 | if (r > 0) {
338 | return r;
339 | } else {
340 | setWriteError();
341 | return 0;
342 | }
343 | }
344 | setWriteError();
345 | return 0;
346 | }
347 |
348 | // This operator is a convenient way for a sketch to check whether the
349 | // port has actually been configured and opened by the host (as opposed
350 | // to just being connected to the host). It can be used, for example, in
351 | // setup() before printing to ensure that an application on the host is
352 | // actually ready to receive and display the data.
353 | // We add a short delay before returning to fix a bug observed by Federico
354 | // where the port is configured (lineState != 0) but not quite opened.
355 | WebUSB::operator bool() {
356 | if (_usbLineInfo.lineState > 0) {
357 | if (!portOpenResult){
358 | if (portOpenPrevLineState == 0) {
359 | portOpenLineStateChangeMillis = millis();
360 | } else {
361 | if (millis()-portOpenLineStateChangeMillis>=10){
362 | portOpenResult = true;
363 | }
364 | }
365 | }
366 | } else {
367 | portOpenResult=false;
368 | }
369 | portOpenPrevLineState = _usbLineInfo.lineState;
370 | return portOpenResult;
371 | }
372 |
373 | unsigned long WebUSB::baud() {
374 | // Disable interrupts while reading a multi-byte value
375 | uint32_t baudrate;
376 | #ifdef ARDUINO_ARCH_SAMD
377 | // nothing needed
378 | #else
379 | // Disable IRQs while reading and clearing breakValue to make
380 | // sure we don't overwrite a value just set by the ISR.
381 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
382 | #endif
383 | baudrate = _usbLineInfo.dwDTERate;
384 | #ifdef ARDUINO_ARCH_SAMD
385 | // nothing needed
386 | #else
387 | }
388 | #endif
389 | return baudrate;
390 | }
391 |
392 | uint8_t WebUSB::stopbits() {
393 | return _usbLineInfo.bCharFormat;
394 | }
395 |
396 | uint8_t WebUSB::paritytype() {
397 | return _usbLineInfo.bParityType;
398 | }
399 |
400 | uint8_t WebUSB::numbits() {
401 | return _usbLineInfo.bDataBits;
402 | }
403 |
404 | bool WebUSB::dtr() {
405 | return _usbLineInfo.lineState & 0x1;
406 | }
407 |
408 | bool WebUSB::rts() {
409 | return _usbLineInfo.lineState & 0x2;
410 | }
411 |
412 | int32_t WebUSB::readBreak() {
413 | int32_t ret;
414 | #ifdef ARDUINO_ARCH_SAMD
415 | uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
416 |
417 | // disable interrupts,
418 | // to avoid clearing a breakValue that might occur
419 | // while processing the current break value
420 | __disable_irq();
421 | #else
422 | // Disable IRQs while reading and clearing breakValue to make
423 | // sure we don't overwrite a value just set by the ISR.
424 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
425 | #endif
426 | ret = breakValue;
427 | breakValue = -1;
428 | #ifdef ARDUINO_ARCH_SAMD
429 | if (enableInterrupts) {
430 | // re-enable the interrupts
431 | __enable_irq();
432 | }
433 | #else
434 | }
435 | #endif
436 | return ret;
437 | }
438 |
--------------------------------------------------------------------------------
/library/WebUSB/WebUSB.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2015, Arduino LLC
3 | Original code (pre-library): Copyright (c) 2011, Peter Barrett
4 |
5 | Permission to use, copy, modify, and/or distribute this software for
6 | any purpose with or without fee is hereby granted, provided that the
7 | above copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 | SOFTWARE.
17 | */
18 |
19 | #ifndef WebUSB_h
20 | #define WebUSB_h
21 |
22 | #include
23 | #include
24 | #ifdef ARDUINO_ARCH_SAMD
25 | #ifdef ARDUINO_API_VERSION
26 | #include "api/PluggableUSB.h"
27 | #else
28 | #include "USB/PluggableUSB.h"
29 | #endif
30 | #else
31 | #include "PluggableUSB.h"
32 | #include
33 | #include
34 | #endif
35 |
36 | #ifndef USBCON
37 | #error "WebUSB requires a board that supports USB client device mode."
38 | #endif
39 |
40 | #define USB_BOS_DESCRIPTOR_TYPE 15
41 | #define WEBUSB_REQUEST_GET_URL 0x02
42 |
43 | #define MS_OS_20_REQUEST_DESCRIPTOR 0x07
44 |
45 | #ifndef WEBUSB_SHORT_NAME
46 | // Max length 20 (ISERIAL_MAX_LEN defined in USBDesc.h)
47 | #define WEBUSB_SHORT_NAME "WUART"
48 | #endif
49 |
50 |
51 | typedef struct
52 | {
53 | InterfaceDescriptor dif;
54 | EndpointDescriptor in;
55 | EndpointDescriptor out;
56 | } WebUSBDescriptor;
57 |
58 | class WebUSB : public PluggableUSBModule, public Stream
59 | {
60 | public:
61 | /*
62 | * Together |landingPageScheme| and |landingPageUrl| tell the browser
63 | * what page the user should visit in order to interact with their
64 | * device. |landingPageScheme| can have any of the following values:
65 | *
66 | * 0x00 -> "http://"
67 | * 0x01 -> "https://"
68 | *
69 | * This prefix is combined with |landingPageUrl| to produce the full
70 | * URL.
71 | */
72 | WebUSB(uint8_t landingPageScheme, const char* landingPageUrl);
73 | void begin(unsigned long);
74 | void begin(unsigned long, uint8_t);
75 | void end(void);
76 | /*
77 | * Sets the string reported as the USB device serial number.
78 | * This should be called before |begin()|, typically in |setup()|.
79 | * |name| should be a pointer to static char array containing
80 | * a nul-terminated string containing at most 20 characters
81 | * (not counting the final nul character).
82 | */
83 | void setShortName(const char* name);
84 |
85 | virtual int available(void);
86 | virtual int peek(void);
87 | virtual int read(void);
88 | int availableForWrite(void);
89 | virtual void flush(void);
90 | virtual size_t write(uint8_t);
91 | virtual size_t write(const uint8_t*, size_t);
92 | using Print::write; // pull in write(str) and write(buf, size) from Print
93 | operator bool();
94 |
95 | volatile uint8_t _rx_buffer_head;
96 | volatile uint8_t _rx_buffer_tail;
97 | unsigned char _rx_buffer[SERIAL_BUFFER_SIZE];
98 |
99 | int32_t readBreak();
100 |
101 | uint32_t baud();
102 | uint8_t stopbits();
103 | uint8_t paritytype();
104 | uint8_t numbits();
105 | bool dtr();
106 | bool rts();
107 | enum {
108 | ONE_STOP_BIT = 0,
109 | ONE_AND_HALF_STOP_BIT = 1,
110 | TWO_STOP_BITS = 2,
111 | };
112 | enum {
113 | NO_PARITY = 0,
114 | ODD_PARITY = 1,
115 | EVEN_PARITY = 2,
116 | MARK_PARITY = 3,
117 | SPACE_PARITY = 4,
118 | };
119 |
120 | protected:
121 | // Implementation of the PluggableUSBModule
122 | int getInterface(uint8_t* interfaceCount);
123 | int getDescriptor(USBSetup& setup);
124 | bool setup(USBSetup& setup);
125 | uint8_t getShortName(char* name);
126 |
127 | private:
128 | bool VendorControlRequest(USBSetup& setup);
129 |
130 | #ifdef ARDUINO_ARCH_SAMD
131 | #ifdef ARDUINO_API_VERSION
132 | unsigned int epType[2];
133 | #else
134 | uint32_t epType[2];
135 | #endif
136 | #else
137 | uint8_t epType[2];
138 | #endif
139 | uint16_t descriptorSize;
140 | uint8_t protocol;
141 | uint8_t idle;
142 | int peek_buffer;
143 | uint8_t landingPageScheme;
144 | const char* landingPageUrl;
145 | const char* shortName;
146 |
147 | bool portOpenResult;
148 | uint8_t portOpenPrevLineState;
149 | unsigned long portOpenLineStateChangeMillis;
150 | };
151 |
152 | #endif // WebUSB_h
153 |
--------------------------------------------------------------------------------
/library/WebUSB/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map HID
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | HID KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 | begin KEYWORD2
15 | SendReport KEYWORD2
16 | AppendDescriptor KEYWORD2
17 |
18 | #######################################
19 | # Constants (LITERAL1)
20 | #######################################
21 | HID_TX LITERAL1
--------------------------------------------------------------------------------
/library/WebUSB/library.properties:
--------------------------------------------------------------------------------
1 | name=WebUSB
2 | version=1.0
3 | author=Arduino
4 | maintainer=Arduino
5 | sentence=Module for PluggableUSB infrastructure. Exposes an API for WebUSB API
6 | paragraph=
7 | category=Communication
8 | url=http://www.arduino.cc/en/Reference/HID
9 | architectures=avr,samd
10 |
--------------------------------------------------------------------------------