@@ -0,0 +1,27 @@ | |||
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. |
@@ -34,9 +34,9 @@ extern const uint16_t fn_actions[]; | |||
/* 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| =| /| *| | |||
* |-----------------------------------------------------------| |-----------| |---------------| | |||
@@ -46,16 +46,16 @@ extern const uint16_t fn_actions[]; | |||
* |-----------------------------------------------------------| ,---. |---------------| | |||
* |Shif|\ | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||
* |Ctrl |Opt |Cmd | Space | |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | | |||
* |Ctrl |Opt |Cmd | Space |App |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | | |||
* `-----------------------------------------------------------' `-----------' `---------------' | |||
*/ | |||
#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, \ | |||
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, \ | |||
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_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \ | |||
@@ -65,12 +65,12 @@ extern const uint16_t fn_actions[]; | |||
{ 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_##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_##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_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_NO, KC_##K7F } \ | |||
} |
@@ -19,20 +19,20 @@ | |||
*/ | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
[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, | |||
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, | |||
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( | |||
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, | |||
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, | |||
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 | |||
), | |||
}; | |||
@@ -23,5 +23,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
void led_set(uint8_t usb_led) | |||
{ | |||
adb_host_kbd_led(~usb_led); | |||
adb_host_kbd_led(ADB_ADDR_KEYBOARD, ~usb_led); | |||
} |
@@ -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; |
@@ -86,9 +86,9 @@ bool adb_host_psw(void) | |||
* <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> | |||
* <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> | |||
*/ | |||
uint16_t adb_host_kbd_recv(void) | |||
uint16_t adb_host_kbd_recv(uint8_t addr) | |||
{ | |||
return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); | |||
return adb_host_talk(addr, ADB_REG_0); | |||
} | |||
#ifdef ADB_MOUSE_ENABLE | |||
@@ -156,11 +156,11 @@ error: | |||
return -n; | |||
} | |||
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) | |||
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) | |||
{ | |||
cli(); | |||
attention(); | |||
send_byte(cmd); | |||
send_byte((addr<<4) | (ADB_CMD_LISTEN<<2) | reg); | |||
place_bit0(); // Stopbit(0) | |||
_delay_us(200); // Tlt/Stop to Start | |||
place_bit1(); // Startbit(1) | |||
@@ -171,12 +171,12 @@ void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) | |||
} | |||
// send state of LEDs | |||
void adb_host_kbd_led(uint8_t led) | |||
void adb_host_kbd_led(uint8_t addr, uint8_t led) | |||
{ | |||
// Addr:Keyboard(0010), Cmd:Listen(10), Register2(10) | |||
// send upper byte (not used) | |||
// send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0: | |||
adb_host_listen(0x2A,0,led&0x07); | |||
// Listen Register2 | |||
// upper byte: not used | |||
// lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock | |||
adb_host_listen(addr, 2, 0, led & 0x07); | |||
} | |||
@@ -325,7 +325,7 @@ Commands | |||
bits commands | |||
------------------------------------------------------ | |||
- - - - 0 0 0 0 Send Request(reset all devices) | |||
- - - - 0 0 0 0 Send Reset(reset all devices) | |||
A A A A 0 0 0 1 Flush(reset a device) | |||
- - - - 0 0 1 0 Reserved | |||
- - - - 0 0 1 1 Reserved | |||
@@ -440,7 +440,7 @@ Address, Handler ID and bits(Register3) | |||
| | | | +-+-+-+----------------- Address | |||
| | | +------------------------- 0 | |||
| | +--------------------------- Service request enable(1 = enabled) | |||
| +----------------------------- Exeptional event(alwyas 1 if not used) | |||
| +----------------------------- Exceptional event(alwyas 1 if not used) | |||
+------------------------------- 0 | |||
ADB Bit Cells |
@@ -53,30 +53,40 @@ POSSIBILITY OF SUCH DAMAGE. | |||
/* ADB commands */ | |||
// Default Address | |||
#define ADB_ADDR_DONGLE 1 | |||
#define ADB_ADDR_KEYBOARD 2 | |||
#define ADB_ADDR_MOUSE 3 | |||
#define ADB_ADDR_TABLET 4 | |||
#define ADB_ADDR_APPLIANCE 7 | |||
// Command Type | |||
#define ADB_CMD_RESET 0 | |||
#define ADB_CMD_FLUSH 1 | |||
#define ADB_CMD_LISTEN 2 | |||
#define ADB_CMD_TALK 3 | |||
// Register | |||
#define ADB_REG_0 0 | |||
#define ADB_REG_1 1 | |||
#define ADB_REG_2 2 | |||
#define ADB_REG_3 3 | |||
/* ADB keyboard handle id */ | |||
#define ADB_HANDLE_M0116 0x01 | |||
#define ADB_HANDLE_M0115 0x02 | |||
#define ADB_HANDLE_M3501 0x02 | |||
#define ADB_HANDLE_M1242 0x10 | |||
/* ADB keyboard handler id */ | |||
#define ADB_HANDLER_M0116 0x01 | |||
#define ADB_HANDLER_IIGS 0x01 | |||
#define ADB_HANDLER_M0115 0x02 | |||
#define ADB_HANDLER_M3501 0x02 | |||
#define ADB_HANDLER_M1242_ANSI 0x10 | |||
#define ADB_HANDLER_EXTENDED_PROTOCOL 0x03 | |||
// ADB host | |||
void adb_host_init(void); | |||
bool adb_host_psw(void); | |||
uint16_t adb_host_kbd_recv(void); | |||
uint16_t adb_host_kbd_recv(uint8_t addr); | |||
uint16_t adb_host_mouse_recv(void); | |||
uint16_t adb_host_talk(uint8_t addr, uint8_t reg); | |||
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l); | |||
void adb_host_kbd_led(uint8_t led); | |||
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l); | |||
void adb_host_kbd_led(uint8_t addr, uint8_t led); | |||
void adb_mouse_task(void); | |||
void adb_mouse_init(void); | |||