Skip to content

Commit 29a672b

Browse files
marcanjannau
authored andcommitted
input: apple: Split off report handling into a separate file
The MTP HID driver will reuse this code, so split it off into another file. Signed-off-by: Hector Martin <[email protected]>
1 parent e50b1e8 commit 29a672b

5 files changed

Lines changed: 182 additions & 129 deletions

File tree

drivers/input/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,13 @@ config TPL_DM_KEYBOARD
3838
includes methods to start/stop the device, check for available
3939
input and update LEDs if the keyboard has them.
4040

41+
config APPLE_KEYB
42+
bool
43+
depends on DM_KEYBOARD
44+
4145
config APPLE_SPI_KEYB
4246
bool "Enable Apple SPI keyboard support"
47+
select APPLE_KEYB
4348
depends on DM_KEYBOARD && DM_SPI
4449
help
4550
This adds a driver for the keyboards found on various

drivers/input/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ obj-$(CONFIG_CPCAP_POWER_BUTTON) += cpcap_pwrbutton.o
1111

1212
ifndef CONFIG_XPL_BUILD
1313

14+
obj-$(CONFIG_APPLE_KEYB) += apple_kbd.o
1415
obj-$(CONFIG_APPLE_SPI_KEYB) += apple_spi_kbd.o
1516
obj-$(CONFIG_I8042_KEYB) += i8042.o
1617
obj-$(CONFIG_TEGRA_KEYBOARD) += input.o tegra-kbc.o

drivers/input/apple_kbd.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2021 Mark Kettenis <[email protected]>
4+
*/
5+
6+
#include <dm.h>
7+
#include <keyboard.h>
8+
#include <spi.h>
9+
#include <stdio_dev.h>
10+
#include <asm-generic/gpio.h>
11+
#include <linux/delay.h>
12+
#include <linux/input.h>
13+
#include "apple_kbd.h"
14+
15+
/*
16+
* The Apple keyboard controllers implement a protocol that
17+
* closely resembles HID Keyboard Boot protocol. The key codes are
18+
* mapped according to the HID Keyboard/Keypad Usage Table.
19+
*/
20+
21+
/* Modifier key bits */
22+
#define HID_MOD_LEFTCTRL BIT(0)
23+
#define HID_MOD_LEFTSHIFT BIT(1)
24+
#define HID_MOD_LEFTALT BIT(2)
25+
#define HID_MOD_LEFTGUI BIT(3)
26+
#define HID_MOD_RIGHTCTRL BIT(4)
27+
#define HID_MOD_RIGHTSHIFT BIT(5)
28+
#define HID_MOD_RIGHTALT BIT(6)
29+
#define HID_MOD_RIGHTGUI BIT(7)
30+
31+
static const u8 hid_kbd_keymap[] = {
32+
KEY_RESERVED, 0xff, 0xff, 0xff,
33+
KEY_A, KEY_B, KEY_C, KEY_D,
34+
KEY_E, KEY_F, KEY_G, KEY_H,
35+
KEY_I, KEY_J, KEY_K, KEY_L,
36+
KEY_M, KEY_N, KEY_O, KEY_P,
37+
KEY_Q, KEY_R, KEY_S, KEY_T,
38+
KEY_U, KEY_V, KEY_W, KEY_X,
39+
KEY_Y, KEY_Z, KEY_1, KEY_2,
40+
KEY_3, KEY_4, KEY_5, KEY_6,
41+
KEY_7, KEY_8, KEY_9, KEY_0,
42+
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB,
43+
KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
44+
KEY_RIGHTBRACE, KEY_BACKSLASH, 0xff, KEY_SEMICOLON,
45+
KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT,
46+
KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
47+
KEY_F3, KEY_F4, KEY_F5, KEY_F6,
48+
KEY_F7, KEY_F8, KEY_F9, KEY_F10,
49+
KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK,
50+
KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
51+
KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
52+
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK,
53+
KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS,
54+
KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3,
55+
KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7,
56+
KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
57+
KEY_BACKSLASH, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL,
58+
};
59+
60+
/* Report ID used for keyboard input reports. */
61+
#define KBD_REPORTID 0x01
62+
63+
static void apple_kbd_service_modifiers(struct input_config *input,
64+
struct apple_kbd_priv *priv)
65+
{
66+
u8 new = priv->new.modifiers;
67+
u8 old = priv->old.modifiers;
68+
69+
if ((new ^ old) & HID_MOD_LEFTCTRL)
70+
input_add_keycode(input, KEY_LEFTCTRL,
71+
old & HID_MOD_LEFTCTRL);
72+
if ((new ^ old) & HID_MOD_RIGHTCTRL)
73+
input_add_keycode(input, KEY_RIGHTCTRL,
74+
old & HID_MOD_RIGHTCTRL);
75+
if ((new ^ old) & HID_MOD_LEFTSHIFT)
76+
input_add_keycode(input, KEY_LEFTSHIFT,
77+
old & HID_MOD_LEFTSHIFT);
78+
if ((new ^ old) & HID_MOD_RIGHTSHIFT)
79+
input_add_keycode(input, KEY_RIGHTSHIFT,
80+
old & HID_MOD_RIGHTSHIFT);
81+
if ((new ^ old) & HID_MOD_LEFTALT)
82+
input_add_keycode(input, KEY_LEFTALT,
83+
old & HID_MOD_LEFTALT);
84+
if ((new ^ old) & HID_MOD_RIGHTALT)
85+
input_add_keycode(input, KEY_RIGHTALT,
86+
old & HID_MOD_RIGHTALT);
87+
if ((new ^ old) & HID_MOD_LEFTGUI)
88+
input_add_keycode(input, KEY_LEFTMETA,
89+
old & HID_MOD_LEFTGUI);
90+
if ((new ^ old) & HID_MOD_RIGHTGUI)
91+
input_add_keycode(input, KEY_RIGHTMETA,
92+
old & HID_MOD_RIGHTGUI);
93+
}
94+
95+
static void apple_kbd_service_key(struct input_config *input,
96+
struct apple_kbd_priv *priv,
97+
int i, int released)
98+
{
99+
u8 *new;
100+
u8 *old;
101+
102+
if (released) {
103+
new = priv->new.keycode;
104+
old = priv->old.keycode;
105+
} else {
106+
new = priv->old.keycode;
107+
old = priv->new.keycode;
108+
}
109+
110+
if (memscan(new, old[i], sizeof(priv->new.keycode)) ==
111+
new + sizeof(priv->new.keycode) &&
112+
old[i] < ARRAY_SIZE(hid_kbd_keymap))
113+
input_add_keycode(input, hid_kbd_keymap[old[i]], released);
114+
}
115+
116+
int apple_kbd_handle_report(struct input_config *input,
117+
struct apple_kbd_priv *priv,
118+
void *data, size_t size)
119+
{
120+
struct apple_kbd_report *report = data;
121+
int i;
122+
123+
if (size < sizeof(struct apple_kbd_report))
124+
return -1;
125+
126+
if (report->reportid != KBD_REPORTID)
127+
return 0;
128+
129+
memcpy(&priv->new, report, sizeof(struct apple_kbd_report));
130+
apple_kbd_service_modifiers(input, priv);
131+
for (i = 0; i < sizeof(priv->new.keycode); i++) {
132+
apple_kbd_service_key(input, priv, i, 1);
133+
apple_kbd_service_key(input, priv, i, 0);
134+
}
135+
memcpy(&priv->old, &priv->new, sizeof(struct apple_kbd_report));
136+
137+
return 1;
138+
}

drivers/input/apple_kbd.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Common code for handling Apple laptop keyboards
4+
*
5+
* Copyright The Asahi Linux Contributors
6+
*/
7+
8+
#ifndef _APPLE_KBD_H
9+
#define _APPLE_KBD_H
10+
11+
#include <input.h>
12+
13+
struct apple_kbd_report {
14+
u8 reportid;
15+
u8 modifiers;
16+
u8 reserved;
17+
u8 keycode[6];
18+
u8 fn;
19+
};
20+
21+
struct apple_kbd_priv {
22+
struct apple_kbd_report old; /* previous keyboard input report */
23+
struct apple_kbd_report new; /* current keyboard input report */
24+
};
25+
26+
int apple_kbd_handle_report(struct input_config *input,
27+
struct apple_kbd_priv *priv,
28+
void *data, size_t size);
29+
30+
#endif

drivers/input/apple_spi_kbd.c

Lines changed: 8 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -10,68 +10,7 @@
1010
#include <asm-generic/gpio.h>
1111
#include <linux/delay.h>
1212
#include <linux/input.h>
13-
14-
/*
15-
* The Apple SPI keyboard controller implements a protocol that
16-
* closely resembles HID Keyboard Boot protocol. The key codes are
17-
* mapped according to the HID Keyboard/Keypad Usage Table.
18-
*/
19-
20-
/* Modifier key bits */
21-
#define HID_MOD_LEFTCTRL BIT(0)
22-
#define HID_MOD_LEFTSHIFT BIT(1)
23-
#define HID_MOD_LEFTALT BIT(2)
24-
#define HID_MOD_LEFTGUI BIT(3)
25-
#define HID_MOD_RIGHTCTRL BIT(4)
26-
#define HID_MOD_RIGHTSHIFT BIT(5)
27-
#define HID_MOD_RIGHTALT BIT(6)
28-
#define HID_MOD_RIGHTGUI BIT(7)
29-
30-
static const u8 hid_kbd_keymap[] = {
31-
KEY_RESERVED, 0xff, 0xff, 0xff,
32-
KEY_A, KEY_B, KEY_C, KEY_D,
33-
KEY_E, KEY_F, KEY_G, KEY_H,
34-
KEY_I, KEY_J, KEY_K, KEY_L,
35-
KEY_M, KEY_N, KEY_O, KEY_P,
36-
KEY_Q, KEY_R, KEY_S, KEY_T,
37-
KEY_U, KEY_V, KEY_W, KEY_X,
38-
KEY_Y, KEY_Z, KEY_1, KEY_2,
39-
KEY_3, KEY_4, KEY_5, KEY_6,
40-
KEY_7, KEY_8, KEY_9, KEY_0,
41-
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB,
42-
KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
43-
KEY_RIGHTBRACE, KEY_BACKSLASH, 0xff, KEY_SEMICOLON,
44-
KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT,
45-
KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
46-
KEY_F3, KEY_F4, KEY_F5, KEY_F6,
47-
KEY_F7, KEY_F8, KEY_F9, KEY_F10,
48-
KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK,
49-
KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
50-
KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
51-
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK,
52-
KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS,
53-
KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3,
54-
KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7,
55-
KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
56-
KEY_BACKSLASH, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL,
57-
};
58-
59-
/* Report ID used for keyboard input reports. */
60-
#define KBD_REPORTID 0x01
61-
62-
struct apple_spi_kbd_report {
63-
u8 reportid;
64-
u8 modifiers;
65-
u8 reserved;
66-
u8 keycode[6];
67-
u8 fn;
68-
};
69-
70-
struct apple_spi_kbd_priv {
71-
struct gpio_desc enable;
72-
struct apple_spi_kbd_report old; /* previous keyboard input report */
73-
struct apple_spi_kbd_report new; /* current keyboard input report */
74-
};
13+
#include "apple_kbd.h"
7514

7615
/* Keyboard device. */
7716
#define KBD_DEVICE 0x01
@@ -100,58 +39,10 @@ struct apple_spi_kbd_msg {
10039
u8 data[0];
10140
};
10241

103-
static void apple_spi_kbd_service_modifiers(struct input_config *input)
104-
{
105-
struct apple_spi_kbd_priv *priv = dev_get_priv(input->dev);
106-
u8 new = priv->new.modifiers;
107-
u8 old = priv->old.modifiers;
108-
109-
if ((new ^ old) & HID_MOD_LEFTCTRL)
110-
input_add_keycode(input, KEY_LEFTCTRL,
111-
old & HID_MOD_LEFTCTRL);
112-
if ((new ^ old) & HID_MOD_RIGHTCTRL)
113-
input_add_keycode(input, KEY_RIGHTCTRL,
114-
old & HID_MOD_RIGHTCTRL);
115-
if ((new ^ old) & HID_MOD_LEFTSHIFT)
116-
input_add_keycode(input, KEY_LEFTSHIFT,
117-
old & HID_MOD_LEFTSHIFT);
118-
if ((new ^ old) & HID_MOD_RIGHTSHIFT)
119-
input_add_keycode(input, KEY_RIGHTSHIFT,
120-
old & HID_MOD_RIGHTSHIFT);
121-
if ((new ^ old) & HID_MOD_LEFTALT)
122-
input_add_keycode(input, KEY_LEFTALT,
123-
old & HID_MOD_LEFTALT);
124-
if ((new ^ old) & HID_MOD_RIGHTALT)
125-
input_add_keycode(input, KEY_RIGHTALT,
126-
old & HID_MOD_RIGHTALT);
127-
if ((new ^ old) & HID_MOD_LEFTGUI)
128-
input_add_keycode(input, KEY_LEFTMETA,
129-
old & HID_MOD_LEFTGUI);
130-
if ((new ^ old) & HID_MOD_RIGHTGUI)
131-
input_add_keycode(input, KEY_RIGHTMETA,
132-
old & HID_MOD_RIGHTGUI);
133-
}
134-
135-
static void apple_spi_kbd_service_key(struct input_config *input, int i,
136-
int released)
137-
{
138-
struct apple_spi_kbd_priv *priv = dev_get_priv(input->dev);
139-
u8 *new;
140-
u8 *old;
141-
142-
if (released) {
143-
new = priv->new.keycode;
144-
old = priv->old.keycode;
145-
} else {
146-
new = priv->old.keycode;
147-
old = priv->new.keycode;
148-
}
149-
150-
if (memscan(new, old[i], sizeof(priv->new.keycode)) ==
151-
new + sizeof(priv->new.keycode) &&
152-
old[i] < ARRAY_SIZE(hid_kbd_keymap))
153-
input_add_keycode(input, hid_kbd_keymap[old[i]], released);
154-
}
42+
struct apple_spi_kbd_priv {
43+
struct gpio_desc enable;
44+
struct apple_kbd_priv kbd;
45+
};
15546

15647
static int apple_spi_kbd_check(struct input_config *input)
15748
{
@@ -160,7 +51,7 @@ static int apple_spi_kbd_check(struct input_config *input)
16051
struct apple_spi_kbd_packet packet;
16152
struct apple_spi_kbd_msg *msg;
16253
struct apple_spi_kbd_report *report;
163-
int i, ret;
54+
int ret;
16455

16556
memset(&packet, 0, sizeof(packet));
16657

@@ -195,20 +86,8 @@ static int apple_spi_kbd_check(struct input_config *input)
19586
msg = (struct apple_spi_kbd_msg *)packet.data;
19687
report = (struct apple_spi_kbd_report *)msg->data;
19788
if (packet.flags == PACKET_READ && packet.device == KBD_DEVICE &&
198-
msg->type == MSG_REPORT && msg->device == KBD_DEVICE &&
199-
msg->cmdlen == sizeof(struct apple_spi_kbd_report) &&
200-
report->reportid == KBD_REPORTID) {
201-
memcpy(&priv->new, report,
202-
sizeof(struct apple_spi_kbd_report));
203-
apple_spi_kbd_service_modifiers(input);
204-
for (i = 0; i < sizeof(priv->new.keycode); i++) {
205-
apple_spi_kbd_service_key(input, i, 1);
206-
apple_spi_kbd_service_key(input, i, 0);
207-
}
208-
memcpy(&priv->old, &priv->new,
209-
sizeof(struct apple_spi_kbd_report));
210-
return 1;
211-
}
89+
msg->type == MSG_REPORT && msg->device == KBD_DEVICE)
90+
return apple_kbd_handle_report(input, &priv->kbd, msg->data, msg->cmdlen);
21291

21392
return 0;
21493

0 commit comments

Comments
 (0)