Skip to content

fix for issue #1295 "leonardo as keyboard does not wake windows 7 from sleep" #1488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
156 changes: 140 additions & 16 deletions hardware/arduino/cores/arduino/HID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

/* Copyright (c) 2011, Peter Barrett
**
** Sleep/Wakeup/SystemControl support added by Michael Dreher
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
Expand Down Expand Up @@ -43,16 +45,21 @@ Keyboard_ Keyboard;
#define RAWHID_TX_SIZE 64
#define RAWHID_RX_SIZE 64

#define HID_REPORTID_MOUSE (1)
#define HID_REPORTID_KEYBOARD (2)
#define HID_REPORTID_RAWHID (3)
#define HID_REPORTID_SYSTEMCONTROL (4)
#define HID_REPORTID_MOUSE_ABS (5)
extern const u8 _hidReportDescriptor[] PROGMEM;
const u8 _hidReportDescriptor[] = {

// Mouse
// Mouse relative
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x85, HID_REPORTID_MOUSE, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
Expand All @@ -76,43 +83,106 @@ const u8 _hidReportDescriptor[] = {
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION

// Keyboard
#ifdef MOUSE_ABS_ENABLED
// Mouse absolute
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, HID_REPORTID_MOUSE_ABS, // REPORT_ID (5)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768)
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#endif

// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x02, // REPORT_ID (2)
0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2)
0x05, 0x07, // USAGE_PAGE (Keyboard)

0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
// Keyboard Modifiers (shift, alt, ...)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)

0x95, 0x08, // REPORT_COUNT (8)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)

0x95, 0x06, // REPORT_COUNT (6)

// Keyboard keys
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x26, 0xDF, 0x00, // LOGICAL_MAXIMUM (239)
0x05, 0x07, // USAGE_PAGE (Keyboard)

0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0xDF, // USAGE_MAXIMUM (Left Control - 1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION

// System Control (Power Down, Sleep, Wakeup, ...)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x80, // USAGE (System Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_SYSTEMCONTROL,// REPORT_ID (4)
0x09, 0x81, // USAGE (System Power Down)
0x09, 0x82, // USAGE (System Sleep)
0x09, 0x83, // USAGE (System Wakeup)
0x09, 0x8E, // USAGE (System Cold Restart)
0x09, 0x8F, // USAGE (System Warm Restart)
0x09, 0xA0, // USAGE (System Dock)
0x09, 0xA1, // USAGE (System Undock)
0x09, 0xA7, // USAGE (System Speaker Mute)
0x09, 0xA8, // USAGE (System Hibernate)
// although these display usages are not that important, they don't cost much more than declaring
// the otherwise necessary constant fill bits
0x09, 0xB0, // USAGE (System Display Invert)
0x09, 0xB1, // USAGE (System Display Internal)
0x09, 0xB2, // USAGE (System Display External)
0x09, 0xB3, // USAGE (System Display Both)
0x09, 0xB4, // USAGE (System Display Dual)
0x09, 0xB5, // USAGE (System Display Toggle Intern/Extern)
0x09, 0xB6, // USAGE (System Display Swap)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x10, // REPORT_COUNT (16)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION

#if RAWHID_ENABLED
// RAW HID
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),

0xA1, 0x01, // Collection 0x01
0x85, 0x03, // REPORT_ID (3)
0x85, HID_REPORTID_RAWHID, // REPORT_ID (3)
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
Expand Down Expand Up @@ -228,8 +298,30 @@ void Mouse_::move(signed char x, signed char y, signed char wheel)
m[1] = x;
m[2] = y;
m[3] = wheel;
HID_SendReport(1,m,4);
HID_SendReport(HID_REPORTID_MOUSE,m,sizeof(m));
}

#ifdef MOUSE_ABS_ENABLED
// all parameters have the range of -32768 to 32767 and must be scaled to screen pixels
// some examples:
// x=0,y=0 is the middle of the screen
// x=-32768,y=-32768 is the top left corner
// x=32767,y=-32768 is the top right corner
// x=32767,y=32767 is the bottom right corner
// x=-32768,y=32767 is the bottom left corner
void Mouse_::moveAbs(int16_t x, int16_t y, int16_t wheel)
{
u8 m[7];
m[0] = _buttons; // TODO: is it a good idea to take over the _buttons from relative report here or should it be left out?
m[1] = LSB(x);
m[2] = MSB(x);
m[3] = LSB(y);
m[4] = MSB(y);
m[5] = LSB(wheel);
m[6] = MSB(wheel);
HID_SendReport(HID_REPORTID_MOUSE_ABS,m,sizeof(m));
}
#endif

void Mouse_::buttons(uint8_t b)
{
Expand Down Expand Up @@ -275,7 +367,7 @@ void Keyboard_::end(void)

void Keyboard_::sendReport(KeyReport* keys)
{
HID_SendReport(2,keys,sizeof(KeyReport));
HID_SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(*keys));
}

extern
Expand Down Expand Up @@ -462,6 +554,38 @@ size_t Keyboard_::press(uint8_t k)
return 1;
}

// System Control
// k is one of the SYSTEM_CONTROL defines which come from the HID usage table "Generic Desktop Page (0x01)"
// in "HID Usage Tables" (HUT1_12v2.pdf)
size_t Keyboard_::systemControl(uint8_t k)
{
if(k <= 16)
{
u16 mask = 0;
u8 m[2];

if(k > 0)
{
mask = 1 << (k - 1);
}

m[0] = LSB(mask);
m[1] = MSB(mask);
HID_SendReport(HID_REPORTID_SYSTEMCONTROL,m,sizeof(m));

// these are all OSCs, so send a clear to make it possible to send it again later
m[0] = 0;
m[1] = 0;
HID_SendReport(HID_REPORTID_SYSTEMCONTROL,m,sizeof(m));
return 1;
}
else
{
setWriteError();
return 0;
}
}

// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
Expand Down Expand Up @@ -517,4 +641,4 @@ size_t Keyboard_::write(uint8_t c)

#endif

#endif /* if defined(USBCON) */
#endif /* if defined(USBCON) */
32 changes: 31 additions & 1 deletion hardware/arduino/cores/arduino/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define __USBAPI__

#if defined(USBCON)
#define MOUSE_ABS_ENABLED

//================================================================================
//================================================================================
Expand All @@ -18,6 +19,7 @@ class USBDevice_
void attach();
void detach(); // Serial port goes down too...
void poll();
bool wakeupHost(); // returns false, when wakeup cannot be processed
};
extern USBDevice_ USBDevice;

Expand Down Expand Up @@ -64,6 +66,9 @@ class Mouse_
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x, signed char y, signed char wheel = 0);
#ifdef MOUSE_ABS_ENABLED
void moveAbs(int16_t x, int16_t y, int16_t wheel); // all parameters have the range of -32768 to 32767 and must be scaled to screen pixels
#endif
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
Expand Down Expand Up @@ -111,6 +116,30 @@ extern Mouse_ Mouse;
#define KEY_F11 0xCC
#define KEY_F12 0xCD


// System Control values for Keyboard_::systemControl()
// these defines come from the HID usage table "Generic Desktop Page (0x01)"
// in the USB standard document "HID Usage Tables" (HUT1_12v2.pdf)
// Currently this list contains only OSC (one shot control) values,
// the implementation of systemControl will have to be changed when
// adding OOC or RTC values.
#define SYSTEM_CONTROL_POWER_DOWN 1
#define SYSTEM_CONTROL_SLEEP 2
#define SYSTEM_CONTROL_WAKEUP 3
#define SYSTEM_CONTROL_COLD_RESTART 4
#define SYSTEM_CONTROL_WARM_RESTART 5
#define SYSTEM_CONTROL_DOCK 6
#define SYSTEM_CONTROL_UNDOCK 7
#define SYSTEM_CONTROL_SPEAKER_MUTE 8
#define SYSTEM_CONTROL_HIBERNATE 9
#define SYSTEM_CONTROL_DISPLAY_INVERT 10
#define SYSTEM_CONTROL_DISPLAY_INTERNAL 11
#define SYSTEM_CONTROL_DISPLAY_EXTERNAL 12
#define SYSTEM_CONTROL_DISPLAY_BOTH 13
#define SYSTEM_CONTROL_DISPLAY_DUAL 14
#define SYSTEM_CONTROL_DISPLAY_TOGGLE_INT_EXT 15
#define SYSTEM_CONTROL_DISPLAY_SWAP 16

// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
Expand All @@ -132,6 +161,7 @@ class Keyboard_ : public Print
virtual size_t press(uint8_t k);
virtual size_t release(uint8_t k);
virtual void releaseAll(void);
virtual size_t systemControl(uint8_t k);
};
extern Keyboard_ Keyboard;

Expand Down Expand Up @@ -193,4 +223,4 @@ void USB_Flush(uint8_t ep);

#endif

#endif /* if defined(USBCON) */
#endif /* if defined(USBCON) */
Loading