adb_usb: Add support for Apple Adjustable keybaord media keys

This commit is contained in:
tmk 2016-06-04 19:29:02 +09:00
parent 230ed4bdef
commit b653b622a6
5 changed files with 124 additions and 30 deletions

View file

@ -39,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
static bool has_media_keys = false;
static bool is_iso_layout = false;
static bool is_modified = false;
static report_mouse_t mouse_report = {};
@ -70,13 +71,26 @@ uint8_t matrix_cols(void)
void matrix_init(void)
{
// LED on
DDRD |= (1<<6); PORTD |= (1<<6);
adb_host_init();
// wait for keyboard to boot up and receive command
_delay_ms(1000);
_delay_ms(2000);
// device scan
xprintf("Before init:\n");
for (uint8_t addr = 1; addr < 16; addr++) {
uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
if (reg3) {
xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
}
_delay_ms(20);
}
// Determine ISO keyboard by handler id
// http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L815
uint16_t handler_id = adb_host_talk(ADB_ADDR_KEYBOARD, 3);
uint16_t handler_id = adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_3);
switch (handler_id) {
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
@ -88,11 +102,27 @@ void matrix_init(void)
break;
}
// Adjustable keyboard media keys: address=0x07 and handlerID=0x02
has_media_keys = (0x02 == (adb_host_talk(ADB_ADDR_APPLIANCE, ADB_REG_3) & 0xff));
if (has_media_keys) {
xprintf("Found: media keys\n");
}
// Enable keyboard left/right modifier distinction
// Addr:Keyboard(0010), Cmd:Listen(10), Register3(11)
// upper byte: reserved bits 0000, device address 0010
// lower byte: device handler 00000011
adb_host_listen(0x2B,0x02,0x03);
// Listen Register3
// upper byte: reserved bits 0000, keyboard address 0010
// lower byte: device handler 00000011
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_PROTOCOL);
// device scan
xprintf("After init:\n");
for (uint8_t addr = 1; addr < 16; addr++) {
uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
if (reg3) {
xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
}
_delay_ms(20);
}
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
@ -103,14 +133,8 @@ void matrix_init(void)
//debug_mouse = true;
print("debug enabled.\n");
// LED flash
DDRD |= (1<<6); PORTD |= (1<<6);
_delay_ms(500);
// LED off
DDRD |= (1<<6); PORTD &= ~(1<<6);
uint16_t handler_id2 = adb_host_talk(ADB_ADDR_KEYBOARD, 3);
xprintf("handler_id: %02X -> %02X\n", (handler_id & 0xff), (handler_id2 & 0xff));
return;
}
@ -192,7 +216,50 @@ uint8_t matrix_scan(void)
if ( codes == 0xFFFF )
{
_delay_ms(12); // delay for preventing overload of poor ADB keyboard controller
codes = adb_host_kbd_recv();
codes = adb_host_kbd_recv(ADB_ADDR_KEYBOARD);
// Adjustable keybaord media keys
if (codes == 0 && has_media_keys &&
(codes = adb_host_kbd_recv(ADB_ADDR_APPLIANCE))) {
// key1
switch (codes & 0x7f ) {
case 0x00: // Mic
codes = (codes & ~0x007f) | 0x42;
break;
case 0x01: // Mute
codes = (codes & ~0x007f) | 0x4a;
break;
case 0x02: // Volume down
codes = (codes & ~0x007f) | 0x49;
break;
case 0x03: // Volume Up
codes = (codes & ~0x007f) | 0x48;
break;
case 0x7F: // no code
break;
default:
xprintf("ERROR: media key1\n");
return 0x11;
}
// key0
switch ((codes >> 8) & 0x7f ) {
case 0x00: // Mic
codes = (codes & ~0x7f00) | (0x42 << 8);
break;
case 0x01: // Mute
codes = (codes & ~0x7f00) | (0x4a << 8);
break;
case 0x02: // Volume down
codes = (codes & ~0x7f00) | (0x49 << 8);
break;
case 0x03: // Volume Up
codes = (codes & ~0x7f00) | (0x48 << 8);
break;
default:
xprintf("ERROR: media key0\n");
return 0x10;
}
}
}
key0 = codes>>8;
key1 = codes&0xFF;