Unverified Commit 0963611f authored by Earle F. Philhower, III's avatar Earle F. Philhower, III Committed by GitHub

Add absolute mouse support (#1342)

Fixes #1338

To be revisited when TinyUSB native support is added and picked up in the SDK
parent 00644db9
......@@ -36,6 +36,7 @@
#include "pico/usb_reset_interface.h"
#include "hardware/watchdog.h"
#include "pico/bootrom.h"
#include "sdkoverride/tusb_absmouse.h"
#include <device/usbd_pvt.h>
// Big, global USB mutex, shared with all USB devices to make sure we don't
......@@ -100,7 +101,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
.iSerialNumber = USBD_STR_SERIAL,
.bNumConfigurations = 1
};
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick && !__USBInstallMassStorage) {
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallAbsoluteMouse && !__USBInstallJoystick && !__USBInstallMassStorage) {
// Can use as-is, this is the default USB case
return (const uint8_t *)&usbd_desc_device;
}
......@@ -108,7 +109,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
if (__USBInstallKeyboard) {
usbd_desc_device.idProduct |= 0x8000;
}
if (__USBInstallMouse) {
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
usbd_desc_device.idProduct |= 0x4000;
}
if (__USBInstallJoystick) {
......@@ -137,7 +138,7 @@ int __USBGetJoystickReportID() {
if (__USBInstallKeyboard) {
i++;
}
if (__USBInstallMouse) {
if (__USBInstallMouse || __USBInstallAbsoluteMouse) {
i++;
}
return i;
......@@ -156,6 +157,7 @@ static uint8_t *GetDescHIDReport(int *len) {
void __SetupDescHIDReport() {
//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;
......@@ -166,6 +168,8 @@ void __SetupDescHIDReport() {
}
if (__USBInstallMouse) {
size += sizeof(desc_hid_report_mouse);
} else if (__USBInstallAbsoluteMouse) {
size += sizeof(desc_hid_report_absmouse);
}
if (__USBInstallJoystick) {
size += sizeof(desc_hid_report_joystick);
......@@ -199,6 +203,14 @@ void __SetupDescHIDReport() {
} else {
memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
}
} else if (__USBInstallAbsoluteMouse) {
//determine if we need an offset (USB keyboard is installed)
if (__USBInstallKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_ABSMOUSE(HID_REPORT_ID(3)) };
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(__hid_report, desc_hid_report_absmouse, sizeof(desc_hid_report_absmouse));
}
}
//3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
......@@ -212,6 +224,9 @@ void __SetupDescHIDReport() {
if (__USBInstallMouse) {
reportid++;
offset += sizeof(desc_hid_report_mouse);
} else if (__USBInstallAbsoluteMouse) {
reportid++;
offset += sizeof(desc_hid_report_absmouse);
}
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
memcpy(__hid_report + offset, desc_local, sizeof(desc_local));
......@@ -235,7 +250,7 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
void __SetupUSBDescriptor() {
if (!usbd_desc_cfg) {
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallAbsoluteMouse || __USBInstallJoystick;
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMassStorage ? 1 : 0);
......
......@@ -23,9 +23,15 @@
// Weak function definitions for each type of endpoint
extern void __USBInstallSerial() __attribute__((weak));
extern void __USBInstallKeyboard() __attribute__((weak));
extern void __USBInstallJoystick() __attribute__((weak));
// One or the other allowed, not both
extern void __USBInstallMouse() __attribute__((weak));
extern void __USBInstallAbsoluteMouse() __attribute__((weak));
extern void __USBInstallMassStorage() __attribute__((weak));
// Big, global USB mutex, shared with all USB devices to make sure we don't
......
/*
Expost absolute mouse HID descriptor and report
Taken from @tobozo PR https://github.com/hathach/tinyusb/pull/1363
TODO - remove once that PR merged with TinyUSB
Copyright (c) 2023 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "tusb.h"
#include "class/hid/hid_device.h"
// Absolute Mouse: same as the Standard (relative) Mouse Report but
// with int16_t instead of int8_t for X and Y coordinates.
typedef struct TU_ATTR_PACKED {
uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
int16_t x; /**< Current x position of the mouse. */
int16_t y; /**< Current y position of the mouse. */
int8_t wheel; /**< Current delta wheel movement on the mouse. */
int8_t pan; // using AC Pan
} hid_abs_mouse_report_t;
// Absolute Mouse Report Descriptor Template
#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
/* Report ID if any */\
__VA_ARGS__ \
HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 5 ) ,\
HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\
/* Left, Right, Middle, Backward, Forward buttons */ \
HID_REPORT_COUNT( 5 ) ,\
HID_REPORT_SIZE ( 1 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* 3 bit padding */ \
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 3 ) ,\
HID_INPUT ( HID_CONSTANT ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
/* X, Y absolute position [0, 32767] */ \
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
HID_LOGICAL_MIN ( 0x00 ) ,\
HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\
HID_REPORT_SIZE ( 16 ) ,\
HID_REPORT_COUNT ( 2 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* Vertical wheel scroll [-127, 127] */ \
HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
HID_LOGICAL_MIN ( 0x81 ) ,\
HID_LOGICAL_MAX ( 0x7f ) ,\
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \
/* Horizontal wheel scroll [-127, 127] */ \
HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \
HID_LOGICAL_MIN ( 0x81 ), \
HID_LOGICAL_MAX ( 0x7f ), \
HID_REPORT_COUNT( 1 ), \
HID_REPORT_SIZE ( 8 ), \
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \
HID_COLLECTION_END , \
HID_COLLECTION_END \
static inline bool tud_hid_abs_mouse_report(uint8_t report_id,
uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
hid_abs_mouse_report_t report = {
.buttons = buttons,
.x = x,
.y = y,
.wheel = vertical,
.pan = horizontal
};
return tud_hid_n_report(0, report_id, &report, sizeof(report));
}
Subproject commit bb7df1fe8c0793669d4f9b12cc8f9108b40e6f25
Subproject commit 8bd9d96bd9aa20df2923b9db69fda7744843a143
:repository-owner: arduino-libraries
:repository-name: Mouse
= {repository-name} Library for Arduino =
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"]
image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"]
This library allows an Arduino board with USB capabilities to act as a Mouse.
For more information about this library please visit us at
https://www.arduino.cc/reference/en/language/functions/usb/mouse/
== License ==
Copyright (c) Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Mouse library
## Methods
### `Mouse.begin()`
Begins emulating the mouse connected to a computer. `begin()` must be called before controlling the computer. To end control, use `Mouse.end()`.
#### Syntax
```
Mouse.begin()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
}
void loop() {
// Initialize the Mouse library when button is pressed
if (digitalRead(2) == HIGH) {
Mouse.begin();
}
}
```
#### See also
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.click()`
Sends a momentary click to the computer at the location of the cursor. This is the same as pressing and immediately releasing the mouse button.
`Mouse.click()` defaults to the left mouse button.
#### Syntax
```
Mouse.click()
Mouse.click(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
}
}
```
#### Notes and warnings
When you use the `Mouse.click()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.end()`
Stops emulating the mouse connected to a computer. To start control, use `Mouse.begin()`.
#### Syntax
```
Mouse.end()
```
#### Parameters
None.
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
pinMode(2, INPUT);
// Initiate the Mouse library
Mouse.begin();
}
void loop() {
// If the button is pressed, send a left mouse click
if (digitalRead(2) == HIGH) {
Mouse.click();
// Then end the Mouse emulation
Mouse.end();
}
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.move()`
Moves the cursor on a connected computer. The motion onscreen is always relative to the cursor’s current location. Before using `Mouse.move()` you must call `Mouse.begin()`.
#### Syntax
```
Mouse.move(xVal, yVal, wheel)
```
#### Parameters
* `xVal`: amount to move along the x-axis. Allowed data types: signed char.
* `yVal`: amount to move along the y-axis. Allowed data types: signed char.
* `wheel`: amount to move scroll wheel. Allowed data types: signed char.
#### Returns
None.
#### Example
```
#include <Mouse.h>
const int xAxis = A1; // Analog sensor for X axis
const int yAxis = A2; // Analog sensor for Y axis
int range = 12; // Output range of X or Y movement
int responseDelay = 2; // Response delay of the mouse, in ms
int threshold = range / 4; // Resting threshold
int center = range / 2; // Resting position value
int minima[] = {1023, 1023}; // Actual analogRead minima for (x, y)
int maxima[] = {0, 0}; // Actual analogRead maxima for (x, y)
int axis[] = {xAxis, yAxis}; // Pin numbers for (x, y)
int mouseReading[2]; // Final mouse readings for (x, y)
void setup() {
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// Read and scale the two axes
int xReading = readAxis(0);
int yReading = readAxis(1);
// Move the mouse
Mouse.move(xReading, yReading, 0);
delay(responseDelay);
}
/*
Reads an axis (0 or 1 for x or y) and scales the
analog input range to a range from 0 to <range>
*/
int readAxis(int axisNumber) {
int distance = 0; // Distance from center of the output range
// Read the analog input
int reading = analogRead(axis[axisNumber]);
// Of the current reading exceeds the max or min for this axis, reset the max or min
if (reading < minima[axisNumber]) {
minima[axisNumber] = reading;
}
if (reading > maxima[axisNumber]) {
maxima[axisNumber] = reading;
}
// Map the reading from the analog input range to the output range
reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);
// If the output reading is outside from the rest position threshold, use it
if (abs(reading - center) > threshold) {
distance = (reading - center);
}
// The Y axis needs to be inverted in order to map the movement correctly
if (axisNumber == 1) {
distance = -distance;
}
// Return the distance for this axis
return distance;
}
```
#### Notes and warnings
When you use the `Mouse.move()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.press()`
Sends a button press to a connected computer. A press is the equivalent of clicking and continuously holding the mouse button. A press is cancelled with `Mouse.release()`. Before using `Mouse.press()`, you need to start communication with `Mouse.begin()`. `Mouse.press()` defaults to a left button press.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button to press (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.press()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.release()](#mouserelease)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.release()`
Sends a message that a previously pressed button (invoked through `Mouse.press()`) is released. `Mouse.release()` defaults to the left button.
#### Syntax
```
Mouse.press()
Mouse.press(button)
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
None.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// If the switch attached to pin 2 is closed, press and hold the left mouse button
if (digitalRead(2) == HIGH) {
Mouse.press();
}
// If the switch attached to pin 3 is closed, release the left mouse button
if (digitalRead(3) == HIGH) {
Mouse.release();
}
}
```
#### Notes and warnings
When you use the `Mouse.release()` command, the Arduino takes over your mouse! Make sure you have control before you use the command. A pushbutton to toggle the mouse control state is effective.
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.isPressed()](#mouseispressed)
### `Mouse.isPressed()`
Checks the current status of all mouse buttons, and reports if any are pressed or not. By default, it checks the status of the left mouse button.
#### Syntax
```
Mouse.isPressed();
Mouse.isPressed(button);
```
#### Parameters
* `button`: which mouse button was released (MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE, default is MOUSE_LEFT).
#### Returns
1 if a button was pressed, 0 if a not.
#### Example
```
#include <Mouse.h>
void setup() {
// The switch that will initiate the Mouse press
pinMode(2, INPUT);
// The switch that will terminate the Mouse press
pinMode(3, INPUT);
// Start serial communication with the computer
Serial.begin(9600);
// Initialize the Mouse library
Mouse.begin();
}
void loop() {
// A variable for checking the button's state
int mouseState = 0;
// If the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variable
if (digitalRead(2) == HIGH) {
Mouse.press();
mouseState = Mouse.isPressed();
}
// If the switch attached to pin 3 is closed, release the left mouse button and save the state in a variable
if (digitalRead(3) == HIGH) {
Mouse.release();
mouseState = Mouse.isPressed();
}
// Print out the current mouse button state
Serial.println(mouseState);
delay(10);
}
```
#### See also
* [Mouse.begin()](#mousebegin)
* [Mouse.click()](#mouseclick)
* [Mouse.end()](#mouseend)
* [Mouse.move()](#mousemove)
* [Mouse.press()](#mousepress)
* [Mouse.release()](#mouserelease)
\ No newline at end of file
# Mouse library
The mouse functions enable 32u4 or SAMD micro based boards to control cursor movement on a connected computer through their micro’s native USB port. When updating the cursor position, it is always relative to the cursor’s previous location.
To use this library:
```
#include <Mouse.h>
```
## Notes and warnings
These core libraries allow the 32u4 and SAMD based boards (Leonardo, Esplora, Zero, Due and MKR Family) to appear as a native Mouse and/or Keyboard to a connected computer.
**A word of caution on using the Mouse and Keyboard libraries**: if the Mouse or Keyboard library is constantly running, it will be difficult to program your board. Functions such as `Mouse.move()` and `Keyboard.print()` will move your cursor or send keystrokes to a connected computer and should only be called when you are ready to handle them. It is recommended to use a control system to turn this functionality on, like a physical switch or only responding to specific input you can control. Refer to the Mouse and Keyboard examples for some ways to handle this.
When using the Mouse or Keyboard library, it may be best to test your output first using `Serial.print()`. This way, you can be sure you know what values are being reported.
## Examples
* [KeyboardAndMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardAndMouseControl): Demonstrates the Mouse and Keyboard commands in one program.
* [ButtonMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ButtonMouseControl): Control cursor movement with 5 pushbuttons.
* [JoystickMouseControl](https://www.arduino.cc/en/Tutorial/BuiltInExamples/JoystickMouseControl): Controls a computer’s cursor movement with a Joystick when a button is pressed.
\ No newline at end of file
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseAbsolute.h>
void setup() {
Serial.begin(115200);
MouseAbsolute.begin();
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a series of circles\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseAbsolute.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
while (BOOTSEL) {
delay(1);
}
}
}
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MouseAbsolute KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
click KEYWORD2
move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
name=MouseAbsolute
version=1.0.1
author=Arduino and EFP3
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
sentence=Allows an Arduino board with USB capabilities to act as a Mouse.
paragraph=Allows the RP2040 to emulate a USB mouse
category=Device Control
url=https://www.arduino.cc/reference/en/language/functions/usb/mouse/
architectures=rp2040
/*
Mouse.cpp
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "MouseAbsolute.h"
#include <RP2040USB.h>
#include "tusb.h"
#include "class/hid/hid_device.h"
#include <sdkoverride/tusb_absmouse.h>
// Weak function override to add our descriptor to the TinyUSB list
void __USBInstallAbsoluteMouse() { /* noop */ }
MouseAbsolute_::MouseAbsolute_(void) : HID_Mouse(true) {
/* noop */
}
void MouseAbsolute_::move(int x, int y, signed char wheel) {
CoreMutex m(&__usb_mutex);
tud_task();
if (tud_hid_ready()) {
tud_hid_abs_mouse_report(__USBGetMouseReportID(), _buttons, limit_xy(x), limit_xy(y), wheel, 0);
}
tud_task();
}
MouseAbsolute_ MouseAbsolute;
/*
Mouse.h
Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MOUSEABSOLUTE_h
#define MOUSEABSOLUTE_h
#include <HID_Mouse.h>
class MouseAbsolute_ : public HID_Mouse {
public:
MouseAbsolute_(void);
virtual void move(int x, int y, signed char wheel = 0) override;
};
extern MouseAbsolute_ MouseAbsolute;
#endif
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseBLE.h>
void setup() {
Serial.begin(115200);
MouseBLE.setAbsolute(true);
MouseBLE.begin("CircleBLE Mouse");
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseBLE.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
MouseBLE.setBattery(random(0, 101)); // Set between 0...100%
while (BOOTSEL) {
delay(1);
}
}
}
......@@ -19,6 +19,7 @@ press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
setBattery KEYWORD2
setAbsolute KEYWORD2
#######################################
# Constants (LITERAL1)
......
......@@ -20,14 +20,16 @@
*/
#include "MouseBLE.h"
#include <sdkoverride/tusb_absmouse.h>
#include <PicoBluetoothBLEHID.h>
MouseBLE_::MouseBLE_(void) {
/* 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))};
void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!localName) {
localName = "PicoW BLE Mouse";
......@@ -35,25 +37,47 @@ void MouseBLE_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, desc_mouse, sizeof(desc_mouse));
PicoBluetoothBLEHID.startHID(localName, hidName, 0x03c2, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
_running = true;
}
void MouseBLE_::end(void) {
PicoBluetoothBLEHID.end();
if (_running) {
PicoBluetoothBLEHID.end();
}
_running = false;
}
void MouseBLE_::setBattery(int lvl) {
PicoBluetoothBLEHID.setBattery(lvl);
if (_running) {
PicoBluetoothBLEHID.setBattery(lvl);
}
}
void MouseBLE_::setAbsolute(bool absolute) {
if (!_running) {
_absolute = absolute;
}
}
void MouseBLE_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
if (!_absolute) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothBLEHID.send(&data, sizeof(data));
}
}
MouseBLE_ MouseBLE;
......@@ -25,12 +25,16 @@
#include <HID_Mouse.h>
class MouseBLE_ : public HID_Mouse {
private:
bool _running;
public:
MouseBLE_(void);
MouseBLE_(bool absolute = false);
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end(void);
virtual void move(int x, int y, signed char wheel = 0) override;
void setBattery(int lvl);
void setAbsolute(bool absolute = true);
};
extern MouseBLE_ MouseBLE;
......
/* Earle F. Philhower, III <earlephilhower@yahoo.com> */
/* Released to the public domain */
#include <MouseBT.h>
void setup() {
Serial.begin(115200);
MouseBT.setAbsolute(true);
MouseBT.begin("CircleBT Mouse");
delay(5000);
Serial.printf("Press BOOTSEL to move the mouse in a circle\n");
}
void loop() {
if (BOOTSEL) {
Serial.println("BARREL ROLLS!!!");
float r = 1000;
for (float cx = 1000; cx <= 16000; cx += 4000) {
for (float cy = 1000; cy <= 16000; cy += 4000) {
for (float a = 0; a < 2.0 * 3.14159; a += 0.1) {
float ax = r * cos(a);
float ay = r * sin(a);
MouseBT.move(ax + cx, ay + cy, 0);
delay(10);
}
}
}
while (BOOTSEL) {
delay(1);
}
}
}
......@@ -18,6 +18,8 @@ move KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
setAbsolute KEYWORD2
#######################################
# Constants (LITERAL1)
......
......@@ -20,14 +20,16 @@
*/
#include "MouseBT.h"
#include <sdkoverride/tusb_absmouse.h>
#include <PicoBluetoothHID.h>
MouseBT_::MouseBT_(void) {
/* 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))};
void MouseBT_::begin(const char *localName, const char *hidName) {
if (!localName) {
......@@ -36,21 +38,41 @@ void MouseBT_::begin(const char *localName, const char *hidName) {
if (!hidName) {
hidName = localName;
}
PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, desc_mouse, sizeof(desc_mouse));
PicoBluetoothHID.startHID(localName, hidName, 0x2580, 33, _absolute ? desc_absmouse : desc_mouse, _absolute ? sizeof(desc_absmouse) : sizeof(desc_mouse));
_running = true;
}
void MouseBT_::end(void) {
PicoBluetoothHID.end();
if (_running) {
PicoBluetoothHID.end();
}
_running = false;
}
void MouseBT_::setAbsolute(bool absolute) {
if (!_running) {
_absolute = absolute;
}
}
void MouseBT_::move(int x, int y, signed char wheel) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
if (!_absolute) {
hid_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
} else {
hid_abs_mouse_report_t data;
data.buttons = _buttons;
data.x = limit_xy(x);
data.y = limit_xy(y);
data.wheel = wheel;
data.pan = 0;
PicoBluetoothHID.send(REPORT_ID, &data, sizeof(data));
}
}
MouseBT_ MouseBT;
......@@ -25,11 +25,15 @@
#include <HID_Mouse.h>
class MouseBT_ : public HID_Mouse {
private:
bool _running;
public:
MouseBT_(void);
MouseBT_(bool absolute = false);
void begin(const char *localName = nullptr, const char *hidName = nullptr);
void end(void);
virtual void move(int x, int y, signed char wheel = 0) override;
void setAbsolute(bool absolute = true);
};
extern MouseBT_ MouseBT;
......
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