From 3778bdaf669ea8e9d397f2b1be71819372e75197 Mon Sep 17 00:00:00 2001 From: Michael Dreher Date: Fri, 5 Jul 2013 20:53:00 +0200 Subject: [PATCH] Added support to press power/sleep/hibernate (and some more) buttons via System Controls. Implemented in Keyboard_::systemControl(). --- hardware/keyboardio/cores/keyboardio/HID.cpp | 112 +++++++++++++----- hardware/keyboardio/cores/keyboardio/USBAPI.h | 25 ++++ .../keyboardio/cores/keyboardio/USBCore.cpp | 2 + 3 files changed, 111 insertions(+), 28 deletions(-) diff --git a/hardware/keyboardio/cores/keyboardio/HID.cpp b/hardware/keyboardio/cores/keyboardio/HID.cpp index 53f0ca82..f216a85e 100644 --- a/hardware/keyboardio/cores/keyboardio/HID.cpp +++ b/hardware/keyboardio/cores/keyboardio/HID.cpp @@ -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. @@ -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_CONSUMERCONTROL (5) extern const u8 _hidReportDescriptor[] PROGMEM; const u8 _hidReportDescriptor[] = { - // Mouse + // Mouse 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) @@ -76,36 +83,65 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION - // Keyboard + // 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) + + 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) + + 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 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 @@ -113,7 +149,7 @@ const u8 _hidReportDescriptor[] = { 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 @@ -131,7 +167,7 @@ const u8 _hidReportDescriptor[] = { 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x09, 0x01, // USAGE (Consumer Control) 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x04, // REPORT_ID (4) + 0x85, HID_REPORTID_CONSUMERCONTROL, // REPORT_ID (4) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) @@ -154,18 +190,6 @@ const u8 _hidReportDescriptor[] = { 0x0a, 0x24, 0x02, // USAGE (www back) 0x10 0x81, 0x62, // INPUT (Data,Var,Abs,NPrf,Null) 0xc0, - // System Control Descriptor - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x80, /* Usage (System Control) */ - 0xA1, 0x01, /* Collection (Application) */ - 0x85, 0x04, /* Report ID 0x05 [SYSTEM CTRL] */ - 0x19, 0x82, /* Usage minimum (System Sleep) */ - 0x29, 0x83, /* Usage maximum (System Wake up) */ - 0x95, 0x02, /* Report count (2) */ - 0x81, 0x06, /*Input (data, variable, relative, Preferred) */ - 0x95, 0x06, /* Report count (6) */ - 0x81, 0x01, /*Input (Constant) */ - 0xC0, /*End Collection */ }; extern const HIDDescriptor _hidInterface PROGMEM; @@ -268,7 +292,7 @@ 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)); } void Mouse_::buttons(uint8_t b) @@ -401,7 +425,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 @@ -588,6 +612,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. @@ -643,4 +699,4 @@ size_t Keyboard_::write(uint8_t c) #endif -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/hardware/keyboardio/cores/keyboardio/USBAPI.h b/hardware/keyboardio/cores/keyboardio/USBAPI.h index 72c50444..bd205097 100644 --- a/hardware/keyboardio/cores/keyboardio/USBAPI.h +++ b/hardware/keyboardio/cores/keyboardio/USBAPI.h @@ -113,6 +113,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 { @@ -134,6 +158,7 @@ public: 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; diff --git a/hardware/keyboardio/cores/keyboardio/USBCore.cpp b/hardware/keyboardio/cores/keyboardio/USBCore.cpp index 6f661760..558a57ab 100644 --- a/hardware/keyboardio/cores/keyboardio/USBCore.cpp +++ b/hardware/keyboardio/cores/keyboardio/USBCore.cpp @@ -2,6 +2,8 @@ /* Copyright (c) 2010, 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.