ADB keyboard handle id | |||||
====================== | |||||
0x01 Apple Standard keyboard M0116 ANSI | |||||
0x01 Apple Desktop Bus keyboard 658-4081 ANSI | |||||
0x02 Apple Extended Keyboard M0115 ANSI | |||||
0x02 Apple Extended Keyboard II M3501 ANSI | |||||
0x03 Logical id for Extended Protocol | |||||
0x10 Apple Adjustable keyboard M1242 ANSI | |||||
Adjustable Keyboard media key | |||||
============================= | |||||
Media key part has different address than the main keyboard(0x02). | |||||
Device Address: 0x07(Appliances/Misc devices) | |||||
Handler ID: 0x02 | |||||
Scan Codes | |||||
---------- | |||||
Media key ADB Code Code in Matix | |||||
----------------------------------------- | |||||
Volume Up: 0x03 0x48 | |||||
Volume Down: 0x02 0x49 | |||||
Mute: 0x01 0x4a | |||||
Mic: 0x00 0x42 | |||||
As for these keys raw ADB codes are translate into logical codes in matrix. |
/* Common layout: ANSI+ISO | /* Common layout: ANSI+ISO | ||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `---' | |||||
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---------------. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |VDn|VUp|Mut|Pwr| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `---------------' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | * ,-----------------------------------------------------------. ,-----------. ,---------------. | ||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| | * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| | ||||
* |-----------------------------------------------------------| |-----------| |---------------| | * |-----------------------------------------------------------| |-----------| |---------------| | ||||
* |-----------------------------------------------------------| ,---. |---------------| | * |-----------------------------------------------------------| ,---. |---------------| | ||||
* |Shif|\ | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | * |Shif|\ | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | ||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | * |-----------------------------------------------------------| ,-----------. |-----------|Ent| | ||||
* |Ctrl |Opt |Cmd | Space | |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | | |||||
* |Ctrl |Opt |Cmd | Space |App |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | | |||||
* `-----------------------------------------------------------' `-----------' `---------------' | * `-----------------------------------------------------------' `-----------' `---------------' | ||||
*/ | */ | ||||
#define KEYMAP( \ | #define KEYMAP( \ | ||||
K35, K7A,K78,K63,K76, K60,K61,K62,K64, K65,K6D,K67,K6F, K69,K6B,K71, K7F, \ | |||||
K35, K7A,K78,K63,K76, K60,K61,K62,K64, K65,K6D,K67,K6F, K69,K6B,K71, K49,K48,K4A,K7F, \ | |||||
K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K72,K73,K74, K47,K51,K4B,K43, \ | K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K72,K73,K74, K47,K51,K4B,K43, \ | ||||
K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, K75,K77,K79, K59,K5B,K5C,K4E, \ | K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, K75,K77,K79, K59,K5B,K5C,K4E, \ | ||||
K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K45, \ | K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K45, \ | ||||
K38,K0A,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K7B, K3E, K53,K54,K55, \ | K38,K0A,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K7B, K3E, K53,K54,K55, \ | ||||
K36,K3A,K37, K31, K7C,K7D, K3B,K3D,K3C, K52, K41,K4C \ | |||||
K36,K3A,K37, K31, K42,K7C,K7D, K3B,K3D,K3C, K52, K41,K4C \ | |||||
) { \ | ) { \ | ||||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ | { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ | ||||
{ KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \ | { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \ | ||||
{ KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \ | { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \ | ||||
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_PENT, KC_##K35, KC_##K36, KC_##K37 }, \ | { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_PENT, KC_##K35, KC_##K36, KC_##K37 }, \ | ||||
{ KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO }, \ | { KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO }, \ | ||||
{ KC_F17, KC_##K41, KC_NO, KC_##K43, KC_F18, KC_##K45, KC_NO, KC_##K47 }, \ | |||||
{ KC_NO, KC_NO, KC_NO, KC_##K4B, KC_##K4C, KC_NO, KC_##K4E, KC_F18 }, \ | |||||
{ KC_F17, KC_##K41, KC_##K42, KC_##K43, KC_F18, KC_##K45, KC_NO, KC_##K47 }, \ | |||||
{ KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_NO, KC_##K4E, KC_F18 }, \ | |||||
{ KC_F19, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \ | { KC_F19, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \ | ||||
{ KC_##K58, KC_##K59, KC_F20, KC_##K5B, KC_##K5C, KC_INT3, KC_INT1, KC_PCMM }, \ | |||||
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_LANG2, KC_##K67 }, \ | |||||
{ KC_LANG1, KC_##K69, KC_F16, KC_##K6B, KC_NO, KC_##K6D, KC_APP, KC_##K6F }, \ | |||||
{ KC_##K58, KC_##K59, KC_F20, KC_##K5B, KC_##K5C, KC_JYEN, KC_RO, KC_PCMM }, \ | |||||
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_HANJ, KC_##K67 }, \ | |||||
{ KC_HAEN, KC_##K69, KC_F16, KC_##K6B, KC_NO, KC_##K6D, KC_APP, KC_##K6F }, \ | |||||
{ KC_NO, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \ | { KC_NO, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \ | ||||
{ KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_NO, KC_##K7F } \ | { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_NO, KC_##K7F } \ | ||||
} | } |
*/ | */ | ||||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
[0] = KEYMAP( | [0] = KEYMAP( | ||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, NO, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, VOLD,VOLU,MUTE,NO, | |||||
FN0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, | FN0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, | ||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,FN1, DEL, END, PGDN, P7, P8, P9, PMNS, | TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,FN1, DEL, END, PGDN, P7, P8, P9, PMNS, | ||||
LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | ||||
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | ||||
LCTL,LALT,LGUI, SPC, RALT,RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
LCTL,LALT,LGUI, SPC, APP, RALT,RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | ), | ||||
[1] = KEYMAP( | [1] = KEYMAP( | ||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, NO, | |||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, VOLD,VOLU,MUTE,NO, | |||||
FN0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, INS, HOME,PGUP, NLCK,BTN1,BTN2,BTN3, | FN0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, INS, HOME,PGUP, NLCK,BTN1,BTN2,BTN3, | ||||
TAB, Q, W, E, R, T, Y, U, PSCR,SLCK,PAUS,UP, INS, FN1, DEL, END, PGDN, WH_D,MS_U,WH_U,WH_D, | TAB, Q, W, E, R, T, Y, U, PSCR,SLCK,PAUS,UP, INS, FN1, DEL, END, PGDN, WH_D,MS_U,WH_U,WH_D, | ||||
LCAP,VOLD,VOLU,MUTE,F, G, H, J, HOME,PGUP,LEFT,RGHT, ENT, MS_L,MS_D,MS_R,WH_U, | LCAP,VOLD,VOLU,MUTE,F, G, H, J, HOME,PGUP,LEFT,RGHT, ENT, MS_L,MS_D,MS_R,WH_U, | ||||
LSFT,NUBS,Z, X, C, V, B, N, M, END, PGDN,DOWN, RSFT, PGUP, WH_L,MS_D,WH_R, | LSFT,NUBS,Z, X, C, V, B, N, M, END, PGDN,DOWN, RSFT, PGUP, WH_L,MS_D,WH_R, | ||||
LCTL,LGUI,LALT, SPC, RGUI,RCTL, HOME,PGDN,END, BTN1, BTN2,BTN3 | |||||
LCTL,LALT,LGUI, SPC, APP, RALT,RCTL, HOME,PGDN,END, BTN1, BTN2,BTN3 | |||||
), | ), | ||||
}; | }; | ||||
void led_set(uint8_t usb_led) | void led_set(uint8_t usb_led) | ||||
{ | { | ||||
adb_host_kbd_led(~usb_led); | |||||
adb_host_kbd_led(ADB_ADDR_KEYBOARD, ~usb_led); | |||||
} | } |
#endif | #endif | ||||
static bool has_media_keys = false; | |||||
static bool is_iso_layout = false; | static bool is_iso_layout = false; | ||||
static bool is_modified = false; | static bool is_modified = false; | ||||
static report_mouse_t mouse_report = {}; | static report_mouse_t mouse_report = {}; | ||||
void matrix_init(void) | void matrix_init(void) | ||||
{ | { | ||||
// LED on | |||||
DDRD |= (1<<6); PORTD |= (1<<6); | |||||
adb_host_init(); | adb_host_init(); | ||||
// wait for keyboard to boot up and receive command | // 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 | // Determine ISO keyboard by handler id | ||||
// http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L815 | // 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) { | switch (handler_id) { | ||||
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: | case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: | ||||
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: | case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: | ||||
break; | 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 | // 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 | // initialize matrix state: all keys off | ||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | ||||
//debug_mouse = true; | //debug_mouse = true; | ||||
print("debug enabled.\n"); | print("debug enabled.\n"); | ||||
// LED flash | |||||
DDRD |= (1<<6); PORTD |= (1<<6); | |||||
_delay_ms(500); | |||||
// LED off | |||||
DDRD |= (1<<6); PORTD &= ~(1<<6); | 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; | return; | ||||
} | } | ||||
if ( codes == 0xFFFF ) | if ( codes == 0xFFFF ) | ||||
{ | { | ||||
_delay_ms(12); // delay for preventing overload of poor ADB keyboard controller | _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; | key0 = codes>>8; | ||||
key1 = codes&0xFF; | key1 = codes&0xFF; |