Unverified Commit 67b3c8fc authored by Benjamin Aigner's avatar Benjamin Aigner Committed by GitHub

Adding a Joystick library, concurrently usable with Keyboard & Mouse (#692)

Co-authored-by: default avatarBenjamin Aigner <beni@asterics-foundation.org>
parent b88ad3d1
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
[submodule "libraries/Mouse"] [submodule "libraries/Mouse"]
path = libraries/Mouse path = libraries/Mouse
url = https://github.com/earlephilhower/Mouse url = https://github.com/earlephilhower/Mouse
[submodule "libraries/Joystick"]
path = libraries/Joystick
url = https://github.com/benjaminaigner/Joystick
[submodule "libraries/Adafruit_TinyUSB_Arduino"] [submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
......
...@@ -91,7 +91,7 @@ const uint8_t *tud_descriptor_device_cb(void) { ...@@ -91,7 +91,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
.iSerialNumber = USBD_STR_SERIAL, .iSerialNumber = USBD_STR_SERIAL,
.bNumConfigurations = 1 .bNumConfigurations = 1
}; };
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallMIDI) { if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick && !__USBInstallMIDI) {
// Can use as-is, this is the default USB case // Can use as-is, this is the default USB case
return (const uint8_t *)&usbd_desc_device; return (const uint8_t *)&usbd_desc_device;
} }
...@@ -102,6 +102,9 @@ const uint8_t *tud_descriptor_device_cb(void) { ...@@ -102,6 +102,9 @@ const uint8_t *tud_descriptor_device_cb(void) {
if (__USBInstallMouse) { if (__USBInstallMouse) {
usbd_desc_device.idProduct |= 0x4000; usbd_desc_device.idProduct |= 0x4000;
} }
if (__USBInstallJoystick) {
usbd_desc_device.idProduct |= 0x0100;
}
if (__USBInstallMIDI) { if (__USBInstallMIDI) {
usbd_desc_device.idProduct |= 0x2000; usbd_desc_device.idProduct |= 0x2000;
} }
...@@ -120,6 +123,17 @@ int __USBGetMouseReportID() { ...@@ -120,6 +123,17 @@ int __USBGetMouseReportID() {
return __USBInstallKeyboard ? 2 : 1; return __USBInstallKeyboard ? 2 : 1;
} }
int __USBGetJoystickReportID() {
int i = 1;
if (__USBInstallKeyboard) {
i++;
}
if (__USBInstallMouse) {
i++;
}
return i;
}
static int __hid_report_len = 0; static int __hid_report_len = 0;
static uint8_t *__hid_report = nullptr; static uint8_t *__hid_report = nullptr;
...@@ -131,37 +145,68 @@ static uint8_t *GetDescHIDReport(int *len) { ...@@ -131,37 +145,68 @@ static uint8_t *GetDescHIDReport(int *len) {
} }
void __SetupDescHIDReport() { void __SetupDescHIDReport() {
if (__USBInstallKeyboard && __USBInstallMouse) { //allocate memory for the HID report descriptors. We don't use them, but need the size here.
uint8_t desc_hid_report[] = { uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) };
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2)) uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)) };
}; int size = 0;
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report));
if (__hid_report) { //accumulate the size of all used HID report descriptors
__hid_report_len = sizeof(desc_hid_report); if (__USBInstallKeyboard) {
memcpy(__hid_report, desc_hid_report, __hid_report_len); size += sizeof(desc_hid_report_keyboard);
}
if (__USBInstallMouse) {
size += sizeof(desc_hid_report_mouse);
}
if (__USBInstallJoystick) {
size += sizeof(desc_hid_report_joystick);
}
//no HID used at all
if (size == 0) {
__hid_report = nullptr;
__hid_report_len = 0;
return;
}
//allocate the "real" HID report descriptor
__hid_report = (uint8_t *)malloc(size);
if (__hid_report) {
__hid_report_len = size;
//now copy the descriptors
//1.) keyboard descriptor, if requested
if (__USBInstallKeyboard) {
memcpy(__hid_report, desc_hid_report_keyboard, sizeof(desc_hid_report_keyboard));
} }
} else if (__USBInstallKeyboard && ! __USBInstallMouse) {
uint8_t desc_hid_report[] = { //2.) mouse descriptor, if necessary. Additional offset & new array is necessary if there is a keyboard.
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)) if (__USBInstallMouse) {
}; //determine if we need an offset (USB keyboard is installed)
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report)); if (__USBInstallKeyboard) {
if (__hid_report) { uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2)) };
__hid_report_len = sizeof(desc_hid_report); memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
memcpy(__hid_report, desc_hid_report, __hid_report_len); } else {
memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
}
} }
} else if (! __USBInstallKeyboard && __USBInstallMouse) {
uint8_t desc_hid_report[] = { //3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) if (__USBInstallJoystick) {
}; uint8_t reportid = 1;
__hid_report = (uint8_t *)malloc(sizeof(desc_hid_report)); int offset = 0;
if (__hid_report) { if (__USBInstallKeyboard) {
__hid_report_len = sizeof(desc_hid_report); reportid++;
memcpy(__hid_report, desc_hid_report, __hid_report_len); offset += sizeof(desc_hid_report_keyboard);
}
if (__USBInstallMouse) {
reportid++;
offset += sizeof(desc_hid_report_mouse);
}
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
memcpy(__hid_report + offset, desc_local, sizeof(desc_local));
} }
} else {
__hid_report = nullptr;
__hid_report_len = 0;
} }
} }
...@@ -181,7 +226,7 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { ...@@ -181,7 +226,7 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
void __SetupUSBDescriptor() { void __SetupUSBDescriptor() {
if (!usbd_desc_cfg) { if (!usbd_desc_cfg) {
bool hasHID = __USBInstallKeyboard || __USBInstallMouse; bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0); uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
// Weak function definitions for each type of endpoint // Weak function definitions for each type of endpoint
extern void __USBInstallSerial() __attribute__((weak)); extern void __USBInstallSerial() __attribute__((weak));
extern void __USBInstallKeyboard() __attribute__((weak)); extern void __USBInstallKeyboard() __attribute__((weak));
extern void __USBInstallJoystick() __attribute__((weak));
extern void __USBInstallMouse() __attribute__((weak)); extern void __USBInstallMouse() __attribute__((weak));
extern void __USBInstallMIDI() __attribute__((weak)); extern void __USBInstallMIDI() __attribute__((weak));
...@@ -34,6 +35,7 @@ extern mutex_t __usb_mutex; ...@@ -34,6 +35,7 @@ extern mutex_t __usb_mutex;
// HID report ID inquiry (report ID will vary depending on the number/type of other HID) // HID report ID inquiry (report ID will vary depending on the number/type of other HID)
int __USBGetKeyboardReportID(); int __USBGetKeyboardReportID();
int __USBGetMouseReportID(); int __USBGetMouseReportID();
int __USBGetJoystickReportID();
// Called by main() to init the USB HW/SW. // Called by main() to init the USB HW/SW.
void __USBStart(); void __USBStart();
...@@ -12,8 +12,9 @@ serial port, ``Serial`` as well as supporting automatic reset-to-upload ...@@ -12,8 +12,9 @@ serial port, ``Serial`` as well as supporting automatic reset-to-upload
from the IDE. from the IDE.
The Arduino-Pico core includes ported versions of the basic Arduino The Arduino-Pico core includes ported versions of the basic Arduino
``Keyboard`` and ``Mouse`` libraries. These libraries allow you to ``Keyboard``, ``Mouse`` and ``Joystick`` libraries. These libraries
emulate a keyboard or mouse with the Pico in your sketches. allow you to emulate a keyboard, a gamepad or mouse (or all together)
with the Pico in your sketches.
See the examples and Arduino Reference at See the examples and Arduino Reference at
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/ https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
......
Subproject commit af745f3e62377de71b7708b15f263dab8773e0c5
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment