Merge pull request #23 from judascleric/master

adding media key support
f13
Ben Blazak 2013-05-05 18:25:20 -07:00
commit f99101c1a0
9 changed files with 205 additions and 19 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
@ -107,13 +108,13 @@ KB_MATRIX_LAYER(
0, 0, 0, 0, 0, 0, 0,
0, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, 0,
0, KEY_SingleQuote_DoubleQuote, 0x34, 0x2F, 0x30, KEY_Equal_Plus,
0, 0x31, KEY_Backslash_Pipe, KEY_Dash_Underscore, KEY_DeleteForward, KEY_DeleteBackspace, 0,
0, 0x31, KEY_Backslash_Pipe, KEY_Dash_Underscore, KEY_DeleteBackspace, KEY_Tab, 0,
KEY_LeftArrow, KEY_RightArrow, KEY_UpArrow, KEY_DownArrow, 0,
0, 0,
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

@ -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