adding media keys

taken from Hasu codebase (https://github.com/tmk/tmk_keyboard) usb.c/.h
and usb_extra.c/.h, though these files only have the PJRC
copyright/license in the header
f13
Ryan Prince 2013-04-14 00:29:47 -07:00
parent 45c901c308
commit 513b82d585
11 changed files with 204 additions and 170 deletions

View File

@ -62,6 +62,7 @@ void kbfun_layer_pop_all(void) {
// DEFINITIONS ----------------------------------------------------------------
#define kprrel &kbfun_press_release
#define kprpst &kbfun_press_release_preserve_sticky
#define mprrel &kbfun_mediakey_press_release
#define ktrans &kbfun_transparent
#define lpush1 &kbfun_layer_push_1
#define lpush2 &kbfun_layer_push_2
@ -113,7 +114,7 @@ KB_MATRIX_LAYER(
0, 0, 0,
0, 0, 0,
// right hand
0, 0, 0, 0, 0, 0, 0,
0, 0, MEDIAKEY_PREV_TRACK, MEDIAKEY_PLAY_PAUSE, MEDIAKEY_NEXT_TRACK, 0, 0,
0, KEY_6_Caret, KEY_7_Ampersand, KEYPAD_Asterisk, KEYPAD_Minus, KEY_GraveAccent_Tilde, 0,
KEYPAD_Plus, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_LeftBracket_LeftBrace, KEY_RightBracket_RightBrace, 0,
0, KEY_GraveAccent_Tilde, KEY_DownArrow, KEY_UpArrow, KEY_LeftArrow, KEY_RightArrow, 0,
@ -187,7 +188,7 @@ KB_MATRIX_LAYER(
NULL, NULL, ktrans,
ktrans, ktrans, ktrans,
// right hand
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
ktrans, ktrans, mprrel, mprrel, mprrel, ktrans, ktrans,
ktrans, sshprre, sshprre, kprrel, kprrel, kprrel, ktrans,
kprrel, sshprre, sshprre, kprrel, kprrel, ktrans,
ktrans, sshprre, kprrel, kprrel, kprrel, kprrel, ktrans,
@ -261,7 +262,7 @@ KB_MATRIX_LAYER(
NULL, NULL, ktrans,
ktrans, ktrans, ktrans,
// right hand
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
ktrans, ktrans, mprrel, mprrel, mprrel, ktrans, ktrans,
ktrans, sshprre, sshprre, kprrel, kprrel, kprrel, ktrans,
kprrel, sshprre, sshprre, kprrel, kprrel, ktrans,
ktrans, sshprre, kprrel, kprrel, kprrel, kprrel, ktrans,

View File

@ -1,106 +0,0 @@
/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/usb_keyboard.html
* Copyright (c) 2009 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define USB_SERIAL_PRIVATE_INCLUDE
#include "usb_extra.h"
#include "usb_keyboard.h"
#include <util/delay.h>
#include <avr/interrupt.h>
/* report id */
#define REPORT_ID_MOUSE 1
#define REPORT_ID_SYSTEM 2
#define REPORT_ID_CONSUMER 3
// audio controls & system controls
// http://www.microsoft.com/whdc/archive/w2kbd.mspx
static const uint8_t PROGMEM extra_hid_report_desc[] = {
/* system control */
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x80, // USAGE (System Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
0x19, 0x01, // USAGE_MINIMUM (0x1)
0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Array,Abs)
0xc0, // END_COLLECTION
/* consumer */
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
0x19, 0x01, // USAGE_MINIMUM (0x1)
0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Array,Abs)
0xc0, // END_COLLECTION
};
int8_t usb_extra_send(uint8_t report_id, uint16_t data)
{
uint8_t intr_state, timeout;
if (!usb_configured()) return -1;
intr_state = SREG;
cli();
UENUM = EXTRA_ENDPOINT;
timeout = UDFNUML + 50;
while (1) {
// are we ready to transmit?
if (UEINTX & (1<<RWAL)) break;
SREG = intr_state;
// has the USB gone offline?
if (!usb_configured()) return -1;
// have we waited too long?
if (UDFNUML == timeout) return -1;
// get ready to try checking again
intr_state = SREG;
cli();
UENUM = EXTRA_ENDPOINT;
}
UEDATX = report_id;
UEDATX = data&0xFF;
UEDATX = (data>>8)&0xFF;
UEINTX = 0x3A;
SREG = intr_state;
return 0;
}
int8_t usb_extra_consumer_send(uint16_t bits)
{
return usb_extra_send(REPORT_ID_CONSUMER, bits);
}
int8_t usb_extra_system_send(uint16_t bits)
{
return usb_extra_send(REPORT_ID_SYSTEM, bits);
}

View File

@ -1,46 +0,0 @@
/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/usb_keyboard.html
* Copyright (c) 2009 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef USB_EXTRA_H
#define USB_EXTRA_H 1
/*
* Enhanced keyboard features for Windows:
* Audio control and System control
*
* http://www.microsoft.com/whdc/archive/w2kbd.mspx
*/
#include <stdint.h>
//#include "usb.h"
#define EXTRA_INTERFACE 3
#define EXTRA_ENDPOINT 4
#define EXTRA_SIZE 8
#define EXTRA_BUFFER EP_DOUBLE_BUFFER
int8_t usb_extra_consumer_send(uint16_t bits);
int8_t usb_extra_system_send(uint16_t bits);
#endif

View File

@ -53,25 +53,31 @@
// operating systems.
#define SUPPORT_ENDPOINT_HALT
/* report id */
#define REPORT_ID_SYSTEM 2
#define REPORT_ID_CONSUMER 3
/**************************************************************************
*
* Endpoint Buffer Configuration
*
**************************************************************************/
#define ENDPOINT0_SIZE 32
#define KEYBOARD_INTERFACE 0
#define KEYBOARD_ENDPOINT 3
#define KEYBOARD_ENDPOINT 1
#define KEYBOARD_SIZE 8
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
#define EXTRA_INTERFACE 1
#define EXTRA_ENDPOINT 2
#define EXTRA_SIZE 8
#define EXTRA_BUFFER EP_DOUBLE_BUFFER
static const uint8_t PROGMEM endpoint_config_table[] = {
0,
0,
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
0
};
@ -142,15 +148,40 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
0xc0 // End Collection
};
#define CONFIG1_DESC_SIZE (9+9+9+7)
#define KEYBOARD_HID_DESC_OFFSET (9+9)
// audio controls & system controls
// http://www.microsoft.com/whdc/archive/w2kbd.mspx
static const uint8_t PROGMEM extra_hid_report_desc[] = {
/* consumer */
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
0x19, 0x01, // USAGE_MINIMUM (0x1)
0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Array,Abs)
0xc0, // END_COLLECTION
};
#define KEYBOARD_HID_DESC_NUM 0
#define KEYBOARD_HID_DESC_OFFSET (9+(9+9+7)*KEYBOARD_HID_DESC_NUM+9)
# define EXTRA_HID_DESC_NUM (KEYBOARD_HID_DESC_NUM + 1)
# define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
#define NUM_INTERFACES (EXTRA_HID_DESC_NUM + 1)
#define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES)
//#define KEYBOARD_HID_DESC_OFFSET (9+9)
static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
LSB(CONFIG1_DESC_SIZE), // wTotalLength
MSB(CONFIG1_DESC_SIZE),
1, // bNumInterfaces
NUM_INTERFACES, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xC0, // bmAttributes
@ -165,22 +196,50 @@ static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
0x01, // bInterfaceSubClass (0x01 = Boot)
0x01, // bInterfaceProtocol (0x01 = Keyboard)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
// HID descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(keyboard_hid_report_desc), // wDescriptorLength
sizeof(keyboard_hid_report_desc), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
KEYBOARD_SIZE, 0, // wMaxPacketSize
1 // bInterval
KEYBOARD_SIZE, 0, // wMaxPacketSize
10, // bInterval
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
EXTRA_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0, // iInterface
// HID descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(extra_hid_report_desc), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
EXTRA_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
EXTRA_SIZE, 0, // wMaxPacketSize
10, // bInterval
};
// If you're desperate for a little extra code memory, these strings
@ -215,10 +274,17 @@ static struct descriptor_list_struct {
const uint8_t *addr;
uint8_t length;
} const PROGMEM descriptor_list[] = {
// DEVICE descriptor
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
// CONFIGURATION descriptor
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
// HID/REPORT descriptors
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
// Extra HID Descriptor
{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
// STRING descriptors
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
@ -258,6 +324,9 @@ static uint8_t keyboard_idle_count=0;
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
volatile uint8_t keyboard_leds=0;
// which consumer key is currently pressed
uint16_t consumer_key;
/**************************************************************************
*
@ -590,4 +659,40 @@ ISR(USB_COM_vect)
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
}
int8_t usb_extra_send(uint8_t report_id, uint16_t data)
{
uint8_t intr_state, timeout;
if (!usb_configured()) return -1;
intr_state = SREG;
cli();
UENUM = EXTRA_ENDPOINT;
timeout = UDFNUML + 50;
while (1) {
// are we ready to transmit?
if (UEINTX & (1<<RWAL)) break;
SREG = intr_state;
// has the USB gone offline?
if (!usb_configured()) return -1;
// have we waited too long?
if (UDFNUML == timeout) return -1;
// get ready to try checking again
intr_state = SREG;
cli();
UENUM = EXTRA_ENDPOINT;
}
UEDATX = report_id;
UEDATX = data&0xFF;
UEDATX = (data>>8)&0xFF;
UEINTX = 0x3A;
SREG = intr_state;
return 0;
}
int8_t usb_extra_consumer_send()
{
return usb_extra_send(REPORT_ID_CONSUMER, consumer_key);
}

View File

@ -12,12 +12,15 @@ extern uint8_t keyboard_modifier_keys;
extern uint8_t keyboard_keys[6];
extern volatile uint8_t keyboard_leds;
extern uint16_t consumer_key;
// This file does not include the HID debug functions, so these empty
// macros replace them with nothing, so users can compile code that
// has calls to these functions.
#define usb_debug_putchar(c)
#define usb_debug_flush_output()
int8_t usb_extra_consumer_send();
#if 0 // removed in favor of equivalent code elsewhere ::Ben Blazak, 2012::
@ -133,8 +136,40 @@ extern volatile uint8_t keyboard_leds;
#endif
/* Consumer Page(0x0C)
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
*/
#define AUDIO_MUTE 0x00E2
#define AUDIO_VOL_UP 0x00E9
#define AUDIO_VOL_DOWN 0x00EA
#define TRANSPORT_NEXT_TRACK 0x00B5
#define TRANSPORT_PREV_TRACK 0x00B6
#define TRANSPORT_STOP 0x00B7
#define TRANSPORT_PLAY_PAUSE 0x00CD
/* application launch */
#define AL_CC_CONFIG 0x0183
#define AL_EMAIL 0x018A
#define AL_CALCULATOR 0x0192
#define AL_LOCAL_BROWSER 0x0194
/* application control */
#define AC_SEARCH 0x0221
#define AC_HOME 0x0223
#define AC_BACK 0x0224
#define AC_FORWARD 0x0225
#define AC_STOP 0x0226
#define AC_REFRESH 0x0227
#define AC_BOOKMARKS 0x022A
/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
#define AL_LOCK 0x019E
#define TRANSPORT_RECORD 0x00B2
#define TRANSPORT_REWIND 0x00B4
#define TRANSPORT_EJECT 0x00B8
#define AC_MINIMIZE 0x0206
/* Generic Desktop Page(0x01) - system power control */
#define SYSTEM_POWER_DOWN 0x0081
#define SYSTEM_SLEEP 0x0082
#define SYSTEM_WAKE_UP 0x0083
// Everything below this point is only intended for usb_serial.c
#ifdef USB_SERIAL_PRIVATE_INCLUDE

View File

@ -16,6 +16,16 @@
#include "../../main.h"
#include "./public.h"
/*
* MediaCodeLookupTable is used to translate from enumeration in keyboard.h to
* consumer key scan code in usb_keyboard.h
*/
static const uint16_t _media_code_lookup_table[] = {
TRANSPORT_PLAY_PAUSE, /* MEDIAKEY_PLAY_PAUSE */
TRANSPORT_PREV_TRACK, /* MEDIAKEY_PREV_TRACK */
TRANSPORT_NEXT_TRACK, /* MEDIAKEY_NEXT_TRACK */
};
// ----------------------------------------------------------------------------
/*
@ -119,3 +129,16 @@ bool _kbfun_is_pressed(uint8_t keycode) {
return false;
}
void _kbfun_mediakey_press_release(bool press, uint8_t keycode) {
uint16_t mediakey_code = _media_code_lookup_table[keycode];
if (press) {
consumer_key = mediakey_code;
} else {
// Only one key can be pressed at a time so only clear the keypress for
// active key (most recently pressed)
if (mediakey_code == consumer_key) {
consumer_key = 0;
}
}
}

View File

@ -21,6 +21,7 @@
void _kbfun_press_release (bool press, uint8_t keycode);
bool _kbfun_is_pressed (uint8_t keycode);
void _kbfun_mediakey_press_release (bool press, uint8_t keycode);
#endif

View File

@ -61,6 +61,7 @@
void kbfun_2_keys_capslock_press_release (void);
void kbfun_layer_push_numpad (void);
void kbfun_layer_pop_numpad (void);
void kbfun_mediakey_press_release (void);
#endif

View File

@ -147,6 +147,20 @@ void kbfun_layer_pop_numpad(void) {
numpad_toggle_numlock();
}
/*
* [name]
* Media Key Press Release
*
* [description]
* Generate a keypress for a media key, such as play/pause, next track, or
* previous track
*
*/
void kbfun_mediakey_press_release(void) {
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
_kbfun_mediakey_press_release(IS_PRESSED, keycode);
}
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */

View File

@ -268,6 +268,11 @@
// (Reserved) 0xE8..0xFFFF // - - - -
// Media key codes are not real scan codes, they must be translated to a 16
// bit number by the consumer key key function
#define MEDIAKEY_PLAY_PAUSE 0x00
#define MEDIAKEY_PREV_TRACK 0x01
#define MEDIAKEY_NEXT_TRACK 0x02
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

View File

@ -117,6 +117,7 @@ int main(void) {
// send the USB report (even if nothing's changed)
usb_keyboard_send();
usb_extra_consumer_send();
_delay_ms(MAKEFILE_DEBOUNCE_TIME);
// update LEDs