Unverified Commit 60e93f3e authored by Benjamin Aigner's avatar Benjamin Aigner Committed by GitHub

BLE HID composite device support (#1587)

* Adapted all libraries to support multiprotocol HID over BT & BLE

* Added ATT DB depending on setup; still no success with working connection

* Added hids_device from BTStack develop branch as override

* Fixing the GATT handle patching, added working ATT DB

* ran astyle on example

* Updates in BLE implementation; WORKING! (but only if all are activated). Removed sdkoverride again, doesn't work.

* Moved ATT DB handles to correct places

* Finally functioning for Mouse+KBD+Joy, and each individual

* Cleaned up code & ran astyle

* Added sdkoverrides to pull develop functions from BTSTack

* Changed a few typos by BTStack to run codespell successfully

* Ran astyle on sdkoverride files

* Added some #if guards for including BTSTack file only if BT is enabled

* Fixed Feature Report value characteristics handle assignment; fixed too long HID report

* Ran astyle
parent 7e8fcc5a
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
Copyright (C) 2014 BlueKitchen GmbH
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
4. Any redistribution, use, or modification is done solely for
personal benefit and not for any commercial purpose or for
monetary gain.
THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Please inquire about commercial licensing options at
contact@bluekitchen-gmbh.com
*/
/**
@title HID Service Server
*/
#ifndef HIDS_DEVICE_H
#define HIDS_DEVICE_H
#if defined ENABLE_CLASSIC
#include <sdkoverride/att_db.h>
#include <stdint.h>
#include "btstack_defines.h"
#include "btstack_hid.h"
#include "bluetooth.h"
#if defined __cplusplus
extern "C" {
#endif
/* API_START */
typedef struct {
uint16_t value_handle;
uint16_t client_configuration_handle;
uint16_t client_configuration_value;
hid_report_type_t type;
uint16_t id;
} hids_device_report_t;
/**
@text Implementation of the GATT HIDS Device
To use with your application, add '#import <hids.gatt>' to your .gatt file
*/
/**
@brief Set up HIDS Device with single INPUT, OUTPUT and FEATURE report
*/
void hids_device_init(uint8_t hid_country_code, const uint8_t * hid_descriptor, uint16_t hid_descriptor_size);
/**
@brief Set up HIDS Device for multiple instances of INPUT, OUTPUT and FEATURE reports
*/
void hids_device_init_with_storage(uint8_t hid_country_code, const uint8_t * hid_descriptor, uint16_t hid_descriptor_size,
uint16_t num_reports, hids_device_report_t * report_storage);
/**
@brief Register callback for the HIDS Device client.
@param callback
*/
void hids_device_register_packet_handler(btstack_packet_handler_t callback);
/**
@brief Request can send now event to send HID Report
Generates an HIDS_SUBEVENT_CAN_SEND_NOW subevent
@param hid_cid
*/
void hids_device_request_can_send_now_event(hci_con_handle_t con_handle);
/**
@brief Send HID Input Report for Report ID
@param con_handle
@param report_id
@param report
@param report_len
@returns status
*/
uint8_t hids_device_send_input_report_for_id(hci_con_handle_t con_handle, uint16_t report_id, const uint8_t * report, uint16_t report_len);
/**
@brief Send HID Input Report for first Input Report
@param con_handle
@param report
@param report_len
@returns status
*/
uint8_t hids_device_send_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len);
/**
@brief Send HID Boot Mouse Input Report
@param con_handle
@param report
@param report_len
@returns status
*/
uint8_t hids_device_send_boot_mouse_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len);
/**
@brief Send HID Boot Mouse Input Report
@param con_handle
@param report
@param report_len
@returns status
*/
uint8_t hids_device_send_boot_keyboard_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len);
/* API_END */
#if defined __cplusplus
}
#endif
#endif
#endif
#include "HID_Bluetooth.h"
//setup the report map.
//more generic function to be used with BLE & BT Classis
void __SetupHIDreportmap(void (*WeakMouse)(), void (*WeakKeyboard)(), void (*WeakJoystick)(), bool absMouse, uint16_t *report_size, uint8_t **reportmap) {
//allocate memory for the HID report descriptors. We don't use them, but need the size here.
uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_absmouse[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(2)) };
int size = 0;
//enable to debug the individual report maps
#if 0
Serial.printf("Report mouse: %d bytes\n", sizeof(desc_hid_report_mouse));
for (uint16_t i = 0; i < sizeof(desc_hid_report_mouse); i++) {
Serial.print(desc_hid_report_mouse[i], HEX);
Serial.print(" ");
if (i % 4 == 3) {
Serial.print("\n");
}
}
Serial.printf("Report absmouse: %d bytes\n", sizeof(desc_hid_report_absmouse));
for (uint16_t i = 0; i < sizeof(desc_hid_report_absmouse); i++) {
Serial.print(desc_hid_report_absmouse[i], HEX);
Serial.print(" ");
if (i % 4 == 3) {
Serial.print("\n");
}
}
Serial.printf("Report kbd: %d bytes\n", sizeof(desc_hid_report_keyboard));
for (uint16_t i = 0; i < sizeof(desc_hid_report_keyboard); i++) {
Serial.print(desc_hid_report_keyboard[i], HEX);
Serial.print(" ");
if (i % 4 == 3) {
Serial.print("\n");
}
}
Serial.printf("Report joystick: %d bytes\n", sizeof(desc_hid_report_joystick));
for (uint16_t i = 0; i < sizeof(desc_hid_report_joystick); i++) {
Serial.print(desc_hid_report_joystick[i], HEX);
Serial.print(" ");
if (i % 4 == 3) {
Serial.print("\n");
}
}
#endif
//accumulate the size of all used HID report descriptors
if (WeakKeyboard) {
size += sizeof(desc_hid_report_keyboard);
}
if (WeakMouse && absMouse == false) {
size += sizeof(desc_hid_report_mouse);
} else if (WeakMouse && absMouse == true) {
size += sizeof(desc_hid_report_absmouse);
}
if (WeakJoystick) {
size += sizeof(desc_hid_report_joystick);
}
//no HID used at all
if (size == 0) {
*report_size = 0;
return;
}
//allocate the "real" HID report descriptor
*reportmap = (uint8_t *)malloc(size);
if (*reportmap) {
*report_size = size;
//now copy the descriptors
//1.) keyboard descriptor, if requested
if (WeakKeyboard) {
memcpy(*reportmap, desc_hid_report_keyboard, sizeof(desc_hid_report_keyboard));
}
//2.) mouse descriptor, if necessary. Additional offset & new array is necessary if there is a keyboard.
if (WeakMouse && absMouse == false) {
//determine if we need an offset (USB keyboard is installed)
if (WeakKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(3)) };
memcpy(*reportmap + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(*reportmap, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
}
} else if (WeakMouse && absMouse == true) {
//determine if we need an offset (USB keyboard is installed)
if (WeakKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(3)) };
memcpy(*reportmap + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(*reportmap, desc_hid_report_absmouse, sizeof(desc_hid_report_absmouse));
}
}
//3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
if (WeakJoystick) {
uint8_t reportid = 1;
int offset = 0;
if (WeakKeyboard) {
reportid += 2;
offset += sizeof(desc_hid_report_keyboard);
}
if (WeakMouse && absMouse == false) {
reportid++;
offset += sizeof(desc_hid_report_mouse);
} else if (WeakMouse && absMouse == true) {
reportid++;
offset += sizeof(desc_hid_report_absmouse);
}
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
memcpy(*reportmap + offset, desc_local, sizeof(desc_local));
}
//enable for debugging the final report map
#if 0
Serial.begin(115200);
Serial.printf("Final map: %d bytes\n", size);
for (uint16_t i = 0; i < size; i++) {
Serial.print(*reportmap[i], HEX);
Serial.print(" ");
if (i % 4 == 3) {
Serial.print("\n");
}
}
#endif
} else {
Serial.println("No report map pointer provided!");
}
}
//get Class of Device number for starting HID, type depends on activated libraries
uint16_t __BTGetCOD() {
//mouse only
if (__BTInstallMouse && !__BTInstallKeyboard && !__BTInstallJoystick) {
return 0x2580;
}
//keyboard only
if (__BTInstallKeyboard && !__BTInstallMouse && !__BTInstallJoystick) {
return 0x2540;
}
//joystick only
if (__BTInstallJoystick && !__BTInstallKeyboard && !__BTInstallMouse) {
return 0x2508;
}
//any other combination will return "combo device"
return 0x25C0;
}
//get Class of Device number for starting HID, type depends on activated libraries
uint16_t __BLEGetAppearance() {
//mouse only
if (__BLEInstallMouse && !__BLEInstallKeyboard && !__BLEInstallJoystick) {
return 0x03C2;
}
//keyboard only
if (__BLEInstallKeyboard && !__BLEInstallMouse && !__BLEInstallJoystick) {
return 0x03C1;
}
//joystick only
if (__BLEInstallJoystick && !__BLEInstallMouse && !__BLEInstallKeyboard) {
return 0x03C4;
}
//any other combination will return "generic HID"
return 0x03C0;
}
//keyboard report id is always 1 (compatibility with iOS)
int __BTGetKeyboardReportID() {
return 1;
}
//
int __BTGetMouseReportID() {
return __BTInstallKeyboard ? 3 : 1;
}
int __BTGetJoystickReportID() {
int i = 1;
if (__BTInstallKeyboard) {
i += 2;
}
if (__BTInstallMouse) {
i++;
}
return i;
}
int __BLEGetKeyboardReportID() {
return 1;
}
int __BLEGetMouseReportID() {
return __BLEInstallKeyboard ? 3 : 1;
}
int __BLEGetFeatureReportID() {
int feature = 1;
if (__BLEInstallKeyboard) {
feature += 2;
}
if (__BLEInstallMouse) {
feature ++;
}
if (__BLEInstallJoystick) {
feature ++;
}
return feature;
}
int __BLEGetJoystickReportID() {
int i = 1;
if (__BLEInstallKeyboard) {
i += 2;
}
if (__BLEInstallMouse) {
i++;
}
return i;
}
......@@ -5,3 +5,39 @@
#ifdef ENABLE_BLE
#include "PicoBluetoothBLEHID.h"
#endif
#pragma once
//necessary to implement the absolute mouse descriptor define,
//remove if merged into TinyUSB
#include <sdkoverride/tusb_absmouse.h>
//override weak declarations to include HID report to report map.
//done in each library (KeyboardBT,...)
extern void __BTInstallKeyboard() __attribute__((weak));
extern void __BTInstallJoystick() __attribute__((weak));
extern void __BTInstallMouse() __attribute__((weak));
//override weak declarations to include HID report to report map.
//done in each library (KeyboardBLE,...)
extern void __BLEInstallKeyboard() __attribute__((weak));
extern void __BLEInstallJoystick() __attribute__((weak));
extern void __BLEInstallMouse() __attribute__((weak));
//setup the report map.
//more generic function to be used with BLE & BT Classis
void __SetupHIDreportmap(void (*WeakMouse)(), void (*WeakKeyboard)(), void (*WeakJoystick)(), bool absMouse, uint16_t *report_size, uint8_t **reportmap);
//get Class of Device number for starting HID, type depends on activated libraries
uint16_t __BTGetCOD();
//get Class of Device number for starting HID, type depends on activated libraries
uint16_t __BLEGetAppearance();
int __BTGetKeyboardReportID();
int __BTGetMouseReportID();
int __BTGetJoystickReportID();
int __BLEGetKeyboardReportID();
int __BLEGetMouseReportID();
int __BLEGetJoystickReportID();
int __BLEGetFeatureReportID();
......@@ -21,6 +21,7 @@
#pragma once
#include <sdkoverride/bluetooth.h>
#include <_needsbt.h>
#include <Arduino.h>
#include <functional>
......@@ -32,6 +33,8 @@
#define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT
#define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT
#define hid_report_type_t hid_report_type_t_bt
#include <sdkoverride/hids_device.h>
#include <sdkoverride/att_db.h>
#include <btstack.h>
#undef hid_report_type_t
#undef HID_REPORT_TYPE_FEATURE
......
......@@ -25,18 +25,22 @@
#include "JoystickBLE.h"
#include <Arduino.h>
#include <HID_Bluetooth.h>
#include <PicoBluetoothBLEHID.h>
//================================================================================
//================================================================================
// Joystick/Gamepad
// Weak function override to add our descriptor to the list
void __BLEInstallJoystick() { /* noop */ }
JoystickBLE_::JoystickBLE_(void) {
// Member vars set in base constructor
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
uint8_t *desc_joystickBLE;
uint16_t desc_joystickBLE_length;
void JoystickBLE_::begin(const char *localName, const char *hidName) {
if (!localName) {
......@@ -45,7 +49,10 @@ void JoystickBLE_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c4, desc_joystick, sizeof(desc_joystick));
__SetupHIDreportmap(__BLEInstallMouse, __BLEInstallKeyboard, __BLEInstallJoystick, false, &desc_joystickBLE_length, &desc_joystickBLE);
PicoBluetoothBLEHID.startHID(localName, hidName, __BLEGetAppearance(), desc_joystickBLE, desc_joystickBLE_length);
}
void JoystickBLE_::end() {
......@@ -57,7 +64,13 @@ void JoystickBLE_::setBattery(int lvl) {
}
void JoystickBLE_::send_now() {
PicoBluetoothBLEHID.send(&data, sizeof(data));
//insert report ID; not part of the hid_gamepad_report_t
uint8_t *report = (uint8_t *)malloc(sizeof(hid_gamepad_report_t) +1);
if (report) {
report[0] = __BLEGetJoystickReportID();
memcpy(&report[1], (uint8_t*)&data, sizeof(data));
PicoBluetoothBLEHID.send(report, sizeof(data) + 1);
}
}
JoystickBLE_ JoystickBLE;
......@@ -25,18 +25,22 @@
#include "JoystickBT.h"
#include <Arduino.h>
#include <HID_Bluetooth.h>
#include <PicoBluetoothHID.h>
//================================================================================
//================================================================================
// Joystick/Gamepad
// Weak function override to add our descriptor to the list
void __BTInstallJoystick() { /* noop */ }
JoystickBT_::JoystickBT_() {
// HID_Joystick sets up all the member vars
}
#define REPORT_ID 0x01
static const uint8_t desc_joystick[] = {TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID))};
uint8_t *desc_joystickBT;
uint16_t desc_joystickBT_length;
void JoystickBT_::begin(const char *localName, const char *hidName) {
if (!localName) {
......@@ -45,7 +49,10 @@ void JoystickBT_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothHID.startHID(localName, hidName, 0x2508, 33, desc_joystick, sizeof(desc_joystick));
__SetupHIDreportmap(__BTInstallMouse, __BTInstallKeyboard, __BTInstallJoystick, false, &desc_joystickBT_length, &desc_joystickBT);
PicoBluetoothHID.startHID(localName, hidName, __BTGetCOD(), 33, desc_joystickBT, desc_joystickBT_length);
}
void JoystickBT_::end() {
......@@ -54,7 +61,7 @@ void JoystickBT_::end() {
//immediately send an HID report
void JoystickBT_::send_now() {
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
PicoBluetoothHID.send(__BTGetJoystickReportID(), &data, sizeof(data));
}
JoystickBT_ JoystickBT;
......@@ -22,19 +22,22 @@
#include "KeyboardBLE.h"
#include "KeyboardLayout.h"
#include <HID_Bluetooth.h>
#include <PicoBluetoothBLEHID.h>
//================================================================================
//================================================================================
// Keyboard
// Weak function override to add our descriptor to the list
void __BLEInstallKeyboard() { /* noop */ }
KeyboardBLE_::KeyboardBLE_(void) {
// Base class clears the members we care about
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID))};
uint8_t *desc_keyboardBLE;
uint16_t desc_keyboardBLE_length;
void KeyboardBLE_::begin(const char *localName, const char *hidName, const uint8_t *layout) {
if (!localName) {
......@@ -44,7 +47,10 @@ void KeyboardBLE_::begin(const char *localName, const char *hidName, const uint8
hidName = localName;
}
_asciimap = layout;
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c1, desc_keyboard, sizeof(desc_keyboard));
__SetupHIDreportmap(__BLEInstallMouse, __BLEInstallKeyboard, __BLEInstallJoystick, false, &desc_keyboardBLE_length, &desc_keyboardBLE);
PicoBluetoothBLEHID.startHID(localName, hidName, __BLEGetAppearance(), desc_keyboardBLE, desc_keyboardBLE_length);
}
void KeyboardBLE_::end(void) {
......@@ -60,12 +66,21 @@ void KeyboardBLE_::sendReport(KeyReport* keys) {
data.modifier = keys->modifiers;
data.reserved = 0;
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
PicoBluetoothBLEHID.send(&data, sizeof(data));
//stitch in report id
static uint8_t report[sizeof(hid_keyboard_report_t) +1];
report[0] = __BLEGetKeyboardReportID();
memcpy(&report[1], (uint8_t*)&data, sizeof(hid_keyboard_report_t));
PicoBluetoothBLEHID.send(&report, sizeof(hid_keyboard_report_t) +1);
}
void KeyboardBLE_::sendConsumerReport(uint16_t key) {
(void) key;
// TODO - Need some BLE-specific code to send 2nd report
uint8_t report[3];
report[0] = __BLEGetKeyboardReportID() + 1; //consumer report id
report[1] = key & 0xFF;
report[2] = (key >> 8) & 0xFF;
PicoBluetoothBLEHID.send(&report, 3);
}
KeyboardBLE_ KeyboardBLE;
......@@ -22,19 +22,22 @@
#include "KeyboardBT.h"
#include "KeyboardLayout.h"
#include <HID_Bluetooth.h>
#include <PicoBluetoothHID.h>
//================================================================================
//================================================================================
// Keyboard
// Weak function override to add our descriptor to the list
void __BTInstallKeyboard() { /* noop */ }
KeyboardBT_::KeyboardBT_(void) {
// Base class clears the members we care about
}
#define REPORT_ID 0x01
static const uint8_t desc_keyboard[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID)), TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID + 1))};
uint8_t *desc_keyboardBT;
uint16_t desc_keyboardBT_length;
static void _hidReportCB(uint16_t cid, hid_report_type_t report_type, uint16_t report_id, int report_size, uint8_t *report) {
(void) cid;
......@@ -56,7 +59,10 @@ void KeyboardBT_::begin(const char *localName, const char *hidName, const uint8_
// Required because the hid_report_type_t overlap in BTStack and TUSB
auto *fcn = (void (*)(short unsigned int, hid_report_type_t_bt, short unsigned int, int, unsigned char*))_hidReportCB;
hid_device_register_report_data_callback(fcn);
PicoBluetoothHID.startHID(localName, hidName, 0x2540, 33, desc_keyboard, sizeof(desc_keyboard));
__SetupHIDreportmap(__BTInstallMouse, __BTInstallKeyboard, __BTInstallJoystick, false, &desc_keyboardBT_length, &desc_keyboardBT);
PicoBluetoothHID.startHID(localName, hidName, __BTGetCOD(), 33, desc_keyboardBT, desc_keyboardBT_length);
}
void KeyboardBT_::end(void) {
......@@ -68,11 +74,11 @@ void KeyboardBT_::sendReport(KeyReport* keys) {
data.modifier = keys->modifiers;
data.reserved = 0;
memcpy(data.keycode, keys->keys, sizeof(data.keycode));
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
PicoBluetoothHID.send(__BLEGetKeyboardReportID(), &data, sizeof(data));
}
void KeyboardBT_::sendConsumerReport(uint16_t key) {
PicoBluetoothHID.send(REPORT_ID + 1, &key, sizeof(key));
PicoBluetoothHID.send(__BLEGetKeyboardReportID() + 1, &key, sizeof(key));
}
KeyboardBT_ KeyboardBT;
/* Earle F. Philhower, III <earlephilhower@yahoo.com>
Benjamin Aigner <beni@asterics-foundation.org> <aignerb@technikum-wien.at> */
/* Released to the public domain */
#define ENABLE_LOG_INFO
#define ENABLE_LOG_DEBUG
#define USE_MOUSE
#define USE_KBD
#define USE_JOYSTICK
#ifdef USE_MOUSE
#include <MouseBLE.h>
#endif
#ifdef USE_KBD
#include <KeyboardBLE.h>
#endif
#ifdef USE_JOYSTICK
#include <JoystickBLE.h>
#endif
void setup() {
Serial.begin(115200);
//If activated nothing happens until the serial port is opened
//while(!Serial);
#if (defined(USE_KBD) || defined(USE_JOYSTICK)) && defined(USE_MOUSE)
MouseBLE.begin("BLE Composite");
#elif defined(USE_MOUSE)
MouseBLE.begin("BLE Mouse");
#endif
#ifdef USE_KBD
KeyboardBLE.begin("BLE KBD");
#endif
#ifdef USE_JOYSTICK
JoystickBLE.begin("BLE JOY");
#endif
Serial.printf("Press BOOTSEL to start action\n");
#ifdef USE_MOUSE
Serial.println("First the mouse moves");
#endif
#ifdef USE_KBD
Serial.println("Then \"Hi\" will be printed");
#endif
#ifdef USE_JOYSTICK
Serial.println("Then joystick buttons & axis are changed");
#endif
}
void loop() {
if (BOOTSEL) {
#ifdef USE_MOUSE
Serial.println("ACTION!!!");
float r = 100;
float ox = 0.0;
float oy = 0.0;
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
float dx = ax - ox;
float dy = ay - oy;
MouseBLE.move(dx, dy, 0);
ox = ax;
oy = ay;
delay(10);
}
MouseBLE.setBattery(random(0, 101)); // Set between 0...100%
delay(1000);
#endif
#ifdef USE_KBD
KeyboardBLE.print("Hi");
#endif
#ifdef USE_JOYSTICK
JoystickBLE.button(1, true);
JoystickBLE.X(0);
JoystickBLE.send_now();
delay(1000);
JoystickBLE.button(1, false);
JoystickBLE.X(512);
JoystickBLE.send_now();
#endif
while (BOOTSEL) {
delay(1);
}
}
}
......@@ -21,15 +21,19 @@
#include "MouseBLE.h"
#include <sdkoverride/tusb_absmouse.h>
#include <HID_Bluetooth.h>
#include <PicoBluetoothBLEHID.h>
// Weak function override to add our descriptor to the list
void __BLEInstallMouse() { /* noop */ }
MouseBLE_::MouseBLE_(bool absolute) : HID_Mouse(absolute) {
_running = false;
}
#define REPORT_ID 0x01
const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))};
const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))};
uint8_t *desc_mouseBLE;
uint16_t desc_mouseBLE_length;
void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!localName) {
localName = "PicoW BLE Mouse";
......@@ -37,7 +41,10 @@ void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
__SetupHIDreportmap(__BLEInstallMouse, __BLEInstallKeyboard, __BLEInstallJoystick, _absolute, &desc_mouseBLE_length, &desc_mouseBLE);
PicoBluetoothBLEHID.startHID(localName, hidName, __BLEGetAppearance(), desc_mouseBLE, desc_mouseBLE_length);
_running = true;
}
......@@ -61,6 +68,8 @@ void MouseBLE_::setAbsolute(bool absolute) {
}
void MouseBLE_::move(int x, int y, signed char wheel) {
static uint8_t report[sizeof(hid_abs_mouse_report_t) +1];
if (!_absolute) {
hid_mouse_report_t data;
data.buttons = _buttons;
......@@ -68,7 +77,10 @@ void MouseBLE_::move(int x, int y, signed char wheel) {
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
report[0] = __BLEGetMouseReportID();
memcpy(&report[1], (uint8_t*)&data, sizeof(data));
PicoBluetoothBLEHID.send(report, sizeof(data) + 1);
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
......@@ -76,7 +88,10 @@ void MouseBLE_::move(int x, int y, signed char wheel) {
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
report[0] = __BLEGetMouseReportID();
memcpy(&report[1], (uint8_t*)&data, sizeof(data));
PicoBluetoothBLEHID.send(report, sizeof(data) + 1);
}
}
......
......@@ -21,15 +21,18 @@
#include "MouseBT.h"
#include <sdkoverride/tusb_absmouse.h>
#include <HID_Bluetooth.h>
#include <PicoBluetoothHID.h>
// Weak function override to add our descriptor to the list
void __BTInstallMouse() { /* noop */ }
MouseBT_::MouseBT_(bool absolute) : HID_Mouse(absolute) {
_running = false;
}
#define REPORT_ID 0x01
const uint8_t desc_mouse[] = {TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID))};
const uint8_t desc_absmouse[] = {TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(REPORT_ID))};
uint8_t *desc_mouseBT;
uint16_t desc_mouseBT_length;
void MouseBT_::begin(const char *localName, const char *hidName) {
if (!localName) {
......@@ -38,7 +41,10 @@ void MouseBT_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
__SetupHIDreportmap(__BTInstallMouse, __BTInstallKeyboard, __BTInstallJoystick, _absolute, &desc_mouseBT_length, &desc_mouseBT);
PicoBluetoothHID.startHID(localName, hidName, __BTGetCOD(), 33, desc_mouseBT, desc_mouseBT_length);
_running = true;
}
......@@ -63,7 +69,7 @@ void MouseBT_::move(int x, int y, signed char wheel) {
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
PicoBluetoothHID.send(__BTGetMouseReportID(), &data, sizeof(data));
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
......@@ -71,7 +77,7 @@ void MouseBT_::move(int x, int y, signed char wheel) {
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
PicoBluetoothHID.send(__BTGetMouseReportID(), &data, sizeof(data));
}
}
......
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