Teensy 3.1: Adding mouse scrolling support for Linux

Logitech wireless keyboard + Teensy 3.1 + USB Host chip

Logitech wireless keyboard + Teensy 3.1 + USB Host chip

I recently started a project with a Teensy 3.1 and USB Host Shield, I dub it my Keyboard/Mouse Macroizer.  The objective was pretty simple: Record and Playback all of the actions one typically does with a keyboard and mouse.  This is fairly unique since it can record not only keyboard actions, but mouse actions too.  Currently I have two of them and they are my default keyboard and mouse both at home and at work.

LCD + 3d printed case

LCD + 3d printed case

Today I’ll just be talking about some modifications needed to the default Teensyduino 1.18 to add the necessary support for mice.  Apparently there is a bug in the linux driver for mice support, that causes the scrolling action on an absolute mouse, to not be processed by linux.  One day I may track it down, but for now, my work a round is to add a second mouse to the USB descriptors that the Teensy passes the OS when it begins the enumeration process.

Just so everyone knows, I’m using Eclipse as my IDE for this project since the Arduino IDE is designed for beginners.  I would have given up in frustration if I had to use the Arduino IDE to develop these project.

A quick summary of the changes I made:

  • Added support for 5 mouse buttons
  • Added an absolute mouse HID
  • Increased the power that the Teensy requests from the USB host (aka computer)
  • Removed support for the joystick (not necessary in my application)

I just went and updated Paul’s latest repo with my changes, which are reflected in the following git diff.  My recommended method of adding these features, if desired, is to use the application provided by Paul to get the base environment, then add the changes from there.

diff –git a/teensy3/keylayouts.h b/teensy3/keylayouts.h
index 220b762..97667c1 100644
— a/teensy3/keylayouts.h
+++ b/teensy3/keylayouts.h
@@ -185,7 +185,7 @@ extern “C”{
#define KEYPAD_9 ( 97 | 0x4000 )
#define KEYPAD_0 ( 98 | 0x4000 )
#define KEYPAD_PERIOD ( 99 | 0x4000 )
-#define KEY_MENU ( 101 | 0x4000 )
+#define KEY_MENU ( 101 | 0x4000 )
#define KEY_F13 ( 104 | 0x4000 )
#define KEY_F14 ( 105 | 0x4000 )
#define KEY_F15 ( 106 | 0x4000 )
diff –git a/teensy3/usb_desc.c b/teensy3/usb_desc.c
index e8225b2..0074548 100644
— a/teensy3/usb_desc.c
+++ b/teensy3/usb_desc.c
@@ -160,14 +160,46 @@ static uint8_t mouse_report_desc[] = {
0xA1, 0x01, // Collection (Application)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
– 0x29, 0x03, // Usage Maximum (Button #3)
+ 0x29, 0x05, // Usage Maximum (Button #5)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
– 0x95, 0x03, // Report Count (3)
+ 0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
– 0x75, 0x05, // Report Size (5)
+ 0x75, 0x03, // Report Size (3)
+ 0x81, 0x03, // Input (Constant)
+ 0x05, 0x01, // Usage Page (Generic Desktop)
+ 0x09, 0x30, // Usage (X)
+ 0x09, 0x31, // Usage (Y)
+ 0x15, 0x81, // Logical Minimum (-127)
+ 0x25, 0x7F, // Logical Maximum (127)
+ 0x75, 0x08, // Report Size (8),
+ 0x95, 0x02, // Report Count (2),
+ 0x81, 0x06, // Input (Data, Variable, Relative)
+ 0x09, 0x38, // Usage (Wheel)
+ 0x95, 0x01, // Report Count (1),
+ 0x81, 0x06, // Input (Data, Variable, Relative)
+ 0xC0 // End Collection
+};
+#endif
+//Comment this out since it doesn’t work as expected with linux
+#ifdef MOUSE_ABS_INTERFACE
+// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+static uint8_t mouse_abs_report_desc[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop)
+ 0x09, 0x02, // Usage (Mouse)
+ 0xA1, 0x01, // Collection (Application)
+ 0x05, 0x09, // Usage Page (Button)
+ 0x19, 0x01, // Usage Minimum (Button #1)
+ 0x29, 0x05, // Usage Maximum (Button #5)
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x95, 0x05, // Report Count (5)
+ 0x75, 0x01, // Report Size (1)
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
+ 0x95, 0x01, // Report Count (1)
+ 0x75, 0x03, // Report Size (3)
0x81, 0x03, // Input (Constant)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
@@ -309,7 +341,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
1, // bConfigurationValue
0, // iConfiguration
0xC0, // bmAttributes
– 50, // bMaxPower
+ 0xFA, // bMaxPower

#ifdef CDC_IAD_DESCRIPTOR
// interface association descriptor, USB ECN, Table 9-Z
@@ -509,8 +541,8 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
– 0x00, // bInterfaceSubClass (0x01 = Boot)
– 0x00, // bInterfaceProtocol (0x02 = Mouse)
+ 0x01, // bInterfaceSubClass (0x01 = Boot)
+ 0x02, // bInterfaceProtocol (0x02 = Mouse)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
@@ -530,6 +562,36 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
MOUSE_INTERVAL, // bInterval
#endif // MOUSE_INTERFACE

+
+#ifdef MOUSE_ABS_INTERFACE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ MOUSE_ABS_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x02 = Mouse)
+ 0, // iInterface
+ // HID interface descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ LSB(sizeof(mouse_abs_report_desc)), // wDescriptorLength
+ MSB(sizeof(mouse_abs_report_desc)),
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ MOUSE_ABS_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ MOUSE_ABS_SIZE, 0, // wMaxPacketSize
+ MOUSE_ABS_INTERVAL, // bInterval
+#endif // MOUSE_INTERFACE
+
#ifdef RAWHID_INTERFACE
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
@@ -762,6 +824,10 @@ const usb_descriptor_list_t usb_descriptor_list[] = {
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)},
{0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9},
#endif
+#ifdef MOUSE_ABS_INTERFACE
+ {0x2200, MOUSE_ABS_INTERFACE, mouse_abs_report_desc, sizeof(mouse_abs_report_desc)},
+ {0x2100, MOUSE_ABS_INTERFACE, config_descriptor+MOUSE_ABS_DESC_OFFSET, 9},
+#endif
#ifdef JOYSTICK_INTERFACE
{0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)},
{0x2100, JOYSTICK_INTERFACE, config_descriptor+JOYSTICK_DESC_OFFSET, 9},
diff –git a/teensy3/usb_desc.h b/teensy3/usb_desc.h
index 958ca36..1b7c9a2 100644
— a/teensy3/usb_desc.h
+++ b/teensy3/usb_desc.h
@@ -164,7 +164,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
– #define CDC_ACM_ENDPOINT 2
+ #define CDC_ACM_ENDPOINT 2
#define CDC_RX_ENDPOINT 3
#define CDC_TX_ENDPOINT 4
#define CDC_ACM_SIZE 16
@@ -178,13 +178,18 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MOUSE_ENDPOINT 5
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 2
– #define JOYSTICK_INTERFACE 4 // Joystick
– #define JOYSTICK_ENDPOINT 6
– #define JOYSTICK_SIZE 16
– #define JOYSTICK_INTERVAL 1
+ #define MOUSE_ABS_INTERFACE 4 // Mouse abs
+ #define MOUSE_ABS_ENDPOINT 6
+ #define MOUSE_ABS_SIZE 8
+ #define MOUSE_ABS_INTERVAL 2
+ //#define JOYSTICK_INTERFACE 5 // Joystick
+ //#define JOYSTICK_ENDPOINT 7
+ //#define JOYSTICK_SIZE 16
+ //#define JOYSTICK_INTERVAL 1
#define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9)
#define MOUSE_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
– #define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
+ #define MOUSE_ABS_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
+ //#define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
@@ -192,6 +197,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
+ //#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY

#elif defined(USB_MIDI)
#define VENDOR_ID 0x16C0
diff –git a/teensy3/usb_inst.cpp b/teensy3/usb_inst.cpp
index dc340ee..7acc2f6 100644
— a/teensy3/usb_inst.cpp
+++ b/teensy3/usb_inst.cpp
@@ -46,6 +46,7 @@ usb_seremu_class Serial;
usb_serial_class Serial;
usb_keyboard_class Keyboard;
usb_mouse_class Mouse;
+usb_mouse_abs_class MouseAbs;
usb_joystick_class Joystick;
uint8_t usb_joystick_class::manual_mode = 0;
#endif
diff –git a/teensy3/usb_mouse.c b/teensy3/usb_mouse.c
index 930687e..7fa1ec5 100644
— a/teensy3/usb_mouse.c
+++ b/teensy3/usb_mouse.c
@@ -39,6 +39,91 @@
// which buttons are currently pressed
uint8_t usb_mouse_buttons_state=0;

+// protocol setting from the host. We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t usb_mouse_protocol=1;
+
+
+// Set the mouse buttons. To create a “click”, 2 calls are needed,
+// one to push the button down and the second to release it
+int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t scroll_left, uint8_t scroll_right)
+//int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right )
+{
+ uint8_t mask=0;
+
+ if (left) mask |= 1;
+ if (middle) mask |= 4;
+ if (right) mask |= 2;
+ if (scroll_left) mask |= 8;
+ if (scroll_right) mask |= 0x10;
+ usb_mouse_buttons_state = mask;
+ return usb_mouse_move(0, 0, 0);
+}
+
+
+// Maximum number of transmit packets to queue so we don’t starve other endpoints for memory
+#define TX_PACKET_LIMIT 3
+
+static uint8_t transmit_previous_timeout=0;
+
+// When the PC isn’t listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 30
+
+#if F_CPU == 96000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+// Move the mouse. x, y and wheel are -127 to 127. Use 0 for no movement.
+int usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
+{
+ uint32_t wait_count=0;
+ usb_packet_t *tx_packet;
+
+ //serial_print(“move”);
+ //serial_print(“\n”);
+ if (x == -128) x = -127;
+ if (y == -128) y = -127;
+ if (wheel == -128) wheel = -127;
+
+ while (1) {
+ if (!usb_configuration) {
+ return -1;
+ }
+ if (usb_tx_packet_count(MOUSE_ENDPOINT) < TX_PACKET_LIMIT) {
+ tx_packet = usb_malloc();
+ if (tx_packet) break;
+ }
+ if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+ transmit_previous_timeout = 1;
+ return -1;
+ }
+ yield();
+ }
+ transmit_previous_timeout = 0;
+ *(tx_packet->buf) = usb_mouse_buttons_state;
+ *(tx_packet->buf + 1) = x;
+ *(tx_packet->buf + 2) = y;
+ *(tx_packet->buf + 3) = wheel;
+ tx_packet->len = 4;
+ usb_tx(MOUSE_ENDPOINT, tx_packet);
+ return 0;
+}
+
+
+
+#endif // MOUSE_INTERFACE
+
+#ifdef MOUSE_ABS_INTERFACE
+
+// which buttons are currently pressed
+uint8_t usb_mouse_abs_buttons_state=0;
+
//#define DEFAULT_XRES 640
//#define DEFAULT_YRES 480

@@ -54,8 +139,8 @@ uint8_t usb_mouse_buttons_state=0;
//#define DEFAULT_XRES 1280
//#define DEFAULT_YRES 800

-#define DEFAULT_XRES 1366
-#define DEFAULT_YRES 768
+//#define DEFAULT_XRES 1366
+//#define DEFAULT_YRES 768

//#define DEFAULT_XRES 1440
//#define DEFAULT_YRES 900
@@ -63,9 +148,23 @@ uint8_t usb_mouse_buttons_state=0;
//#define DEFAULT_XRES 1920
//#define DEFAULT_YRES 1080

+//#define DEFAULT_XRES 1920
+//#define DEFAULT_YRES 1080
+
//#define DEFAULT_XRES 2560
//#define DEFAULT_YRES 1440

+
+
+//#define DEFAULT_XRES 3840
+#define DEFAULT_XRES 1920
+#define DEFAULT_YRES 1080
+
+//#define DEFAULT_XRES 1600
+//#define DEFAULT_YRES 900
+
+
+
//#define DEFAULT_XRES 2560
//#define DEFAULT_YRES 1600

@@ -75,6 +174,10 @@ uint8_t usb_mouse_buttons_state=0;
//#define DEFAULT_XRES 3840
//#define DEFAULT_YRES 2160

+//#define DEFAULT_XRES 3840
+//#define DEFAULT_YRES 1200
+
+
//#define DEFAULT_XRES 7680
//#define DEFAULT_YRES 4320

@@ -94,22 +197,24 @@ static uint32_t usb_mouse_offset_y=DEFAULT_YSCALE/2-1;

// Set the mouse buttons. To create a “click”, 2 calls are needed,
// one to push the button down and the second to release it
-int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right)
+int usb_mouse_abs_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t scroll_left, uint8_t scroll_right)
{
uint8_t mask=0;

if (left) mask |= 1;
if (middle) mask |= 4;
if (right) mask |= 2;
– usb_mouse_buttons_state = mask;
– return usb_mouse_move(0, 0, 0);
+ if (scroll_left) mask |= 8;
+ if (scroll_right) mask |= 0x10;
+ usb_mouse_abs_buttons_state = mask;
+ return usb_mouse_abs_move(0, 0, 0);
}

// Maximum number of transmit packets to queue so we don’t starve other endpoints for memory
#define TX_PACKET_LIMIT 3

-static uint8_t transmit_previous_timeout=0;
+static uint8_t transmit_previous_abs_timeout=0;

// When the PC isn’t listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30
@@ -124,7 +229,7 @@ static uint8_t transmit_previous_timeout=0;

// Move the mouse. x, y and wheel are -127 to 127. Use 0 for no movement.
-int usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
+int usb_mouse_abs_move(int8_t x, int8_t y, int8_t wheel)
{
uint32_t wait_count=0, val32;
usb_packet_t *tx_packet;
@@ -155,18 +260,18 @@ int usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
if (!usb_configuration) {
return -1;
}
– if (usb_tx_packet_count(MOUSE_ENDPOINT) < TX_PACKET_LIMIT) {
+ if (usb_tx_packet_count(MOUSE_ABS_ENDPOINT) < TX_PACKET_LIMIT) {
tx_packet = usb_malloc();
if (tx_packet) break;
}
– if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+ if (++wait_count > TX_TIMEOUT || transmit_previous_abs_timeout) {
transmit_previous_timeout = 1;
return -1;
}
yield();
}
– transmit_previous_timeout = 0;
– *(tx_packet->buf) = usb_mouse_buttons_state;
+ transmit_previous_abs_timeout = 0;
+ *(tx_packet->buf) = usb_mouse_abs_buttons_state;
val32 = usb_mouse_position_x * usb_mouse_scale_x + usb_mouse_offset_x;
//serial_print(“move:”);
//serial_phex16(usb_mouse_position_x);
@@ -184,20 +289,26 @@ int usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
*(tx_packet->buf + 4) = val32 >> 24;
*(tx_packet->buf + 5) = wheel;
tx_packet->len = 6;
– usb_tx(MOUSE_ENDPOINT, tx_packet);
+ usb_tx(MOUSE_ABS_ENDPOINT, tx_packet);
return 0;
}

-int usb_mouse_position(uint16_t x, uint16_t y)
+int usb_mouse_abs_position(uint16_t x, uint16_t y)
{
if (x >= usb_mouse_resolution_x) x = usb_mouse_resolution_x – 1;
usb_mouse_position_x = x;
if (y >= usb_mouse_resolution_y) y = usb_mouse_resolution_y – 1;
usb_mouse_position_y = y;
– return usb_mouse_move(0, 0, 0);
+ return usb_mouse_abs_move(0, 0, 0);
+}
+
+void usb_mouse_abs_current_position(uint16_t * x, uint16_t * y)
+{
+ *x = usb_mouse_position_x;
+ *y = usb_mouse_position_y;
}

-void usb_mouse_screen_size(uint16_t width, uint16_t height, uint8_t mac)
+void usb_mouse_abs_screen_size(uint16_t width, uint16_t height, uint8_t mac)
{
if (width < 128) width = 128;
else if (width > 7680) width = 7680;
@@ -223,4 +334,4 @@ void usb_mouse_screen_size(uint16_t width, uint16_t height, uint8_t mac)

-#endif // MOUSE_INTERFACE
+#endif
diff –git a/teensy3/usb_mouse.h b/teensy3/usb_mouse.h
index e6c6e0c..cdb5fb3 100644
— a/teensy3/usb_mouse.h
+++ b/teensy3/usb_mouse.h
@@ -39,11 +39,21 @@
#ifdef __cplusplus
extern “C” {
#endif
-int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right);
+//int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right);
+int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t scroll_left, uint8_t scroll_right);
int usb_mouse_move(int8_t x, int8_t y, int8_t wheel);
int usb_mouse_position(uint16_t x, uint16_t y);
void usb_mouse_screen_size(uint16_t width, uint16_t height, uint8_t mac);
extern uint8_t usb_mouse_buttons_state;
+extern uint8_t usb_mouse_protocol;
+
+//ABS mouse functions
+extern uint8_t usb_mouse_abs_buttons_state;
+int usb_mouse_abs_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t scroll_left, uint8_t scroll_right);
+int usb_mouse_abs_move(int8_t x, int8_t y, int8_t wheel);
+int usb_mouse_abs_position(uint16_t x, uint16_t y);
+void usb_mouse_abs_screen_size(uint16_t width, uint16_t height, uint8_t mac);
+void usb_mouse_abs_current_position(uint16_t * x, uint16_t * y);
#ifdef __cplusplus
}
#endif
@@ -52,7 +62,9 @@ extern uint8_t usb_mouse_buttons_state;
#define MOUSE_LEFT 1
#define MOUSE_MIDDLE 4
#define MOUSE_RIGHT 2
-#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
+#define MOUSE_SCROLL_LEFT 8
+#define MOUSE_SCROLL_RIGHT 16
+#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_SCROLL_LEFT | MOUSE_SCROLL_RIGHT)

// C++ interface
#ifdef __cplusplus
@@ -61,11 +73,7 @@ class usb_mouse_class
public:
void begin(void) { }
void end(void) { }
– void move(int8_t x, int8_t y, int8_t wheel=0) { usb_mouse_move(x, y, wheel); }
– void moveTo(uint16_t x, uint16_t y) { usb_mouse_position(x, y); }
– void screenSize(uint16_t width, uint16_t height, bool isMacintosh = false) {
– usb_mouse_screen_size(width, height, isMacintosh ? 1 : 0);
– }
+ int move(int8_t x, int8_t y, int8_t wheel=0) { usb_mouse_move(x, y, wheel); }
void click(uint8_t b = MOUSE_LEFT) {
usb_mouse_buttons_state = b;
usb_mouse_move(0, 0, 0);
@@ -73,8 +81,8 @@ class usb_mouse_class
usb_mouse_move(0, 0, 0);
}
void scroll(int8_t wheel) { usb_mouse_move(0, 0, wheel); }
– void set_buttons(uint8_t left, uint8_t middle=0, uint8_t right=0) {
– usb_mouse_buttons(left, middle, right);
+ void set_buttons(uint8_t left, uint8_t middle=0, uint8_t right=0, uint8_t scroll_left = 0, uint8_t scroll_right = 0) {
+ usb_mouse_buttons(left, middle, right, scroll_left, scroll_right);
}
void press(uint8_t b = MOUSE_LEFT) {
uint8_t buttons = usb_mouse_buttons_state | (b & MOUSE_ALL);
@@ -96,6 +104,47 @@ class usb_mouse_class
};
extern usb_mouse_class Mouse;

+class usb_mouse_abs_class
+{
+ public:
+ void begin(void) { }
+ void end(void) { }
+ void move(int8_t x, int8_t y, int8_t wheel=0) { usb_mouse_abs_move(x, y, wheel); }
+ void moveTo(uint16_t x, uint16_t y) { usb_mouse_abs_position(x, y); }
+ void screenSize(uint16_t width, uint16_t height, bool isMacintosh = false) {
+ usb_mouse_abs_screen_size(width, height, isMacintosh ? 1 : 0);
+ }
+ void click(uint8_t b = MOUSE_LEFT) {
+ usb_mouse_abs_buttons_state = b;
+ usb_mouse_abs_move(0, 0, 0);
+ usb_mouse_abs_buttons_state = 0;
+ usb_mouse_abs_move(0, 0, 0);
+ }
+ void scroll(int8_t wheel) { usb_mouse_abs_move(0, 0, wheel); }
+ void set_buttons(uint8_t left, uint8_t middle=0, uint8_t right=0, uint8_t scroll_left = 0, uint8_t scroll_right = 0) {
+ usb_mouse_abs_buttons(left, middle, right, scroll_left, scroll_right);
+ }
+ void press(uint8_t b = MOUSE_LEFT) {
+ uint8_t buttons = usb_mouse_abs_buttons_state | (b & MOUSE_ALL);
+ if (buttons != usb_mouse_abs_buttons_state) {
+ usb_mouse_abs_buttons_state = buttons;
+ usb_mouse_abs_move(0, 0, 0);
+ }
+ }
+ void release(uint8_t b = MOUSE_LEFT) {
+ uint8_t buttons = usb_mouse_abs_buttons_state & ~(b & MOUSE_ALL);
+ if (buttons != usb_mouse_abs_buttons_state) {
+ usb_mouse_abs_buttons_state = buttons;
+ usb_mouse_abs_move(0, 0, 0);
+ }
+ }
+ bool isPressed(uint8_t b = MOUSE_ALL) {
+ return ((usb_mouse_buttons_state & (b & MOUSE_ALL)) != 0);
+ }
+};
+
+extern usb_mouse_abs_class MouseAbs;
+
#endif // __cplusplus

#endif // USB_HID || USB_SERIAL_HID

That’s it for now, once I get my keyboard/mouse macroizer polished some more, I’ll post more about it.  Till then, I’ll be using it every day.

Here’s a preview of what the saved keyboard keystrokes look like when I type the phrase: The lazy cat jumps over the dog.

D:1269,1,S;
K:216,2,S,t;
D:120,1,0;
K:40,2,0,null;
K:72,2,0,h;
K:128,2,0,null;
K:16,2,0,e;
K:144,2,0,null;
K:24,2,0,space;
K:80,2,0,null;
K:192,2,0,l;
K:128,2,0,null;
K:16,2,0,a;
K:120,2,0,null;
K:144,2,0,z;
K:184,2,0,null;
K:48,2,0,y;
K:80,2,0,null;
K:80,2,0,space;
K:96,2,0,null;
K:297,2,0,c;
K:80,3,0,c,a;
K:64,3,0,null,a;
K:80,2,0,null;
K:64,2,0,t;
K:120,3,0,t,space;
K:24,3,0,null,space;
K:96,2,0,null;
K:88,2,0,j;
K:120,2,0,null;
K:88,2,0,u;
K:80,2,0,null;
K:136,2,0,m;
K:97,3,0,m,p;
K:48,3,0,null,p;
K:120,2,0,null;
K:80,2,0,s;
K:184,2,0,null;
K:88,2,0,space;
K:96,2,0,null;
K:64,2,0,o;
K:120,2,0,null;
K:24,2,0,v;
K:120,2,0,null;
K:32,2,0,e;
K:162,3,0,e,r;
K:80,3,0,null,r;
K:56,2,0,null;
K:24,2,0,space;
K:104,3,0,space,t;
K:16,3,0,null,t;
K:104,3,0,h,t;
K:64,2,0,h;
K:56,3,0,h,e;
K:16,3,0,null,e;
K:112,3,0,space,e;
K:40,2,0,space;
K:104,2,0,null;
K:16,2,0,d;
K:144,3,0,d,o;
K:16,3,0,null,o;
K:128,2,0,null;
K:16,2,0,g;
K:145,2,0,null;
K:104,2,0,period;
K:80,2,0,null;

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s