o Make keyboard-related properties to be compatible with vendor standard

o Allow setting keymap in FDT, use hardcoded one by default
o Represent fallback keymap as a list rather than directly usable M*N array

Submitted by:	Maxim Ignatenko <gelraen.ua@gmail.com>
This commit is contained in:
Ruslan Bukin 2014-05-30 06:45:50 +00:00
parent 1a31ec5e51
commit 17f65b3a8d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266872
4 changed files with 222 additions and 113 deletions

View File

@ -105,9 +105,6 @@ __FBSDID("$FreeBSD$");
#define CKB_FLAG_POLLING 0x2
#define KBD_DRIVER_NAME "ckbd"
/* TODO: take interrupt from DTS */
#define KB_GPIO_INT 146
struct ckb_softc {
keyboard_t sc_kbd;
keymap_t sc_keymap;
@ -130,9 +127,11 @@ struct ckb_softc {
int flag;
int rows;
int cols;
int gpio;
device_t dev;
device_t gpio_dev;
struct thread *sc_poll_thread;
uint16_t *keymap;
uint8_t *scan_local;
uint8_t *scan;
@ -199,7 +198,7 @@ static int
ckb_intr(keyboard_t *kbd, void *arg)
{
return (0);
return (0);
}
/* lock the access to the keyboard, not used */
@ -207,7 +206,7 @@ static int
ckb_lock(keyboard_t *kbd, int lock)
{
return (1);
return (1);
}
/* clear the internal state of the keyboard */
@ -309,20 +308,33 @@ ckb_read(keyboard_t *kbd, int wait)
return (0);
}
int scantokey(int i, int j);
int
scantokey(int i, int j)
static uint16_t
keymap_read(struct ckb_softc *sc, int col, int row)
{
int k;
for (k = 0; k < KEYMAP_LEN; k++)
if ((keymap[k].col == i) && (keymap[k].row == j))
return (keymap[k].key);
KASSERT(sc->keymap != NULL, "keymap_read: no keymap");
if (col >= 0 && col < sc->cols &&
row >= 0 && row < sc->rows) {
return sc->keymap[row * sc->cols + col];
}
return (0);
}
static int
keymap_write(struct ckb_softc *sc, int col, int row, uint16_t key)
{
KASSERT(sc->keymap != NULL, "keymap_write: no keymap");
if (col >= 0 && col < sc->cols &&
row >= 0 && row < sc->rows) {
sc->keymap[row * sc->cols + col] = key;
return (0);
}
return (-1);
}
/* read char from the keyboard */
static uint32_t
ckb_read_char_locked(keyboard_t *kbd, int wait)
@ -350,9 +362,10 @@ ckb_read_char_locked(keyboard_t *kbd, int wait)
if (sc->sc_flags & CKB_FLAG_POLLING) {
for (;;) {
GPIO_PIN_GET(sc->gpio_dev, KB_GPIO_INT, &status);
GPIO_PIN_GET(sc->gpio_dev, sc->gpio, &status);
if (status == 0) {
if (ec_command(EC_CMD_MKBP_STATE, sc->scan, sc->cols,
if (ec_command(EC_CMD_MKBP_STATE, sc->scan,
sc->cols,
sc->scan, sc->cols)) {
return (NOKEY);
}
@ -373,7 +386,7 @@ ckb_read_char_locked(keyboard_t *kbd, int wait)
if (oldbit == newbit)
continue;
key = scantokey(i,j);
key = keymap_read(sc, i, j);
if (key == 0) {
continue;
};
@ -666,27 +679,109 @@ dummy_kbd_configure(int flags)
KEYBOARD_DRIVER(ckbd, ckbdsw, dummy_kbd_configure);
/*
* Parses 'keymap' into sc->keymap.
* Requires sc->cols and sc->rows to be set.
*/
static int
parse_keymap(struct ckb_softc *sc, pcell_t *keymap, size_t len)
{
int i;
sc->keymap = malloc(sc->cols * sc->rows * sizeof(sc->keymap[0]),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (sc->keymap == NULL) {
return (ENOMEM);
}
for (i = 0; i < len; i++) {
/*
* Return value is ignored, we just write whatever fits into
* specified number of rows and columns and silently ignore
* everything else.
* Keymap entries follow this format: 0xRRCCKKKK
* RR - row number, CC - column number, KKKK - key code
*/
keymap_write(sc, (keymap[i] >> 16) & 0xff,
(keymap[i] >> 24) & 0xff,
keymap[i] & 0xffff);
}
return (0);
}
/* Allocates a new array for keymap and returns it in 'keymap'. */
static int
read_keymap(phandle_t node, const char *prop, pcell_t **keymap, size_t *len)
{
if ((*len = OF_getproplen(node, prop)) <= 0) {
return (ENXIO);
}
if ((*keymap = malloc(*len, M_DEVBUF, M_NOWAIT)) == NULL) {
return (ENOMEM);
}
if (OF_getencprop(node, prop, *keymap, *len) != *len) {
return (ENXIO);
}
return (0);
}
static int
parse_dts(struct ckb_softc *sc)
{
phandle_t node;
pcell_t dts_value;
int len;
pcell_t *keymap;
int len, ret;
const char *keymap_prop = NULL;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
if ((len = OF_getproplen(node, "keypad,num-rows")) <= 0)
if ((len = OF_getproplen(node, "google,key-rows")) <= 0)
return (ENXIO);
OF_getprop(node, "keypad,num-rows", &dts_value, len);
OF_getprop(node, "google,key-rows", &dts_value, len);
sc->rows = fdt32_to_cpu(dts_value);
if ((len = OF_getproplen(node, "keypad,num-columns")) <= 0)
if ((len = OF_getproplen(node, "google,key-columns")) <= 0)
return (ENXIO);
OF_getprop(node, "keypad,num-columns", &dts_value, len);
OF_getprop(node, "google,key-columns", &dts_value, len);
sc->cols = fdt32_to_cpu(dts_value);
if ((sc->rows == 0) || (sc->cols == 0))
if ((len = OF_getproplen(node, "freebsd,intr-gpio")) <= 0)
return (ENXIO);
OF_getprop(node, "freebsd,intr-gpio", &dts_value, len);
sc->gpio = fdt32_to_cpu(dts_value);
if (OF_hasprop(node, "freebsd,keymap")) {
keymap_prop = "freebsd,keymap";
device_printf(sc->dev, "using FreeBSD-specific keymap from FDT\n");
} else if (OF_hasprop(node, "linux,keymap")) {
keymap_prop = "linux,keymap";
device_printf(sc->dev, "using Linux keymap from FDT\n");
} else {
device_printf(sc->dev, "using built-in keymap\n");
}
if (keymap_prop != NULL) {
if ((ret = read_keymap(node, keymap_prop, &keymap, &len))) {
device_printf(sc->dev,
"failed to read keymap from FDT: %d\n", ret);
return (ret);
}
ret = parse_keymap(sc, keymap, len);
free(keymap, M_DEVBUF);
if (ret) {
return (ret);
}
} else {
if ((ret = parse_keymap(sc, default_keymap, KEYMAP_LEN))) {
return (ret);
}
}
if ((sc->rows == 0) || (sc->cols == 0) || (sc->gpio == 0))
return (ENXIO);
return (0);
@ -721,6 +816,7 @@ chrome_kb_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
sc->keymap = NULL;
if ((error = parse_dts(sc)) != 0)
return error;
@ -736,8 +832,7 @@ chrome_kb_attach(device_t dev)
sc->cols, sc->rows);
#endif
/* TODO: take interrupt from DTS */
pad_setup_intr(KB_GPIO_INT, ckb_ec_intr, sc);
pad_setup_intr(sc->gpio, ckb_ec_intr, sc);
kbd = &sc->sc_kbd;
rid = 0;
@ -786,7 +881,8 @@ chrome_kb_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb")) {
if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb") ||
ofw_bus_is_compatible(dev, "google,mkbp-keyb")) {
device_set_desc(dev, "Chrome EC Keyboard");
return (BUS_PROBE_DEFAULT);
}
@ -794,9 +890,24 @@ chrome_kb_probe(device_t dev)
return (ENXIO);
}
static int
chrome_kb_detach(device_t dev)
{
struct ckb_softc *sc;
sc = device_get_softc(dev);
if (sc->keymap != NULL) {
free(sc->keymap, M_DEVBUF);
}
return 0;
}
static device_method_t chrome_kb_methods[] = {
DEVMETHOD(device_probe, chrome_kb_probe),
DEVMETHOD(device_attach, chrome_kb_attach),
DEVMETHOD(device_detach, chrome_kb_detach),
{ 0, 0 }
};

View File

@ -26,97 +26,93 @@
* $FreeBSD$
*/
void ckb_ec_intr(void *);
#include <dev/ofw/openfirm.h>
struct key {
uint8_t row;
uint8_t col;
uint8_t key;
};
void ckb_ec_intr(void *);
#define KEYMAP_LEN 75
struct key keymap[KEYMAP_LEN] = {
{ 0x00, 0x01, 0x7d }, /* lmeta */
{ 0x00, 0x02, 0x3b }, /* F1 */
{ 0x00, 0x03, 0x30 }, /* B */
{ 0x00, 0x04, 0x44 }, /* F10 */
{ 0x00, 0x06, 0x31 }, /* N */
{ 0x00, 0x08, 0x0d }, /* = */
{ 0x00, 0x0a, 0x64 }, /* ralt */
pcell_t default_keymap[KEYMAP_LEN] = {
0x0001007d, /* lmeta */
0x0002003b, /* F1 */
0x00030030, /* B */
0x00040044, /* F10 */
0x00060031, /* N */
0x0008000d, /* = */
0x000a0064, /* ralt */
{ 0x01, 0x01, 0x01 }, /* escape */
{ 0x01, 0x02, 0x3e }, /* F4 */
{ 0x01, 0x03, 0x22 }, /* G */
{ 0x01, 0x04, 0x41 }, /* F7 */
{ 0x01, 0x06, 0x23 }, /* H */
{ 0x01, 0x08, 0x28 }, /* ' */
{ 0x01, 0x09, 0x43 }, /* F9 */
{ 0x01, 0x0b, 0x0e }, /* backspace */
0x01010001, /* escape */
0x0102003e, /* F4 */
0x01030022, /* G */
0x01040041, /* F7 */
0x01060023, /* H */
0x01080028, /* ' */
0x01090043, /* F9 */
0x010b000e, /* backspace */
{ 0x02, 0x00, 0x1d }, /* lctrl */
{ 0x02, 0x01, 0x0f }, /* tab */
{ 0x02, 0x02, 0x3d }, /* F3 */
{ 0x02, 0x03, 0x14 }, /* t */
{ 0x02, 0x04, 0x40 }, /* F6 */
{ 0x02, 0x05, 0x1b }, /* ] */
{ 0x02, 0x06, 0x15 }, /* y */
{ 0x02, 0x07, 0x56 }, /* 102nd */
{ 0x02, 0x08, 0x1a }, /* [ */
{ 0x02, 0x09, 0x42 }, /* F8 */
0x0200001d, /* lctrl */
0x0201000f, /* tab */
0x0202003d, /* F3 */
0x02030014, /* t */
0x02040040, /* F6 */
0x0205001b, /* ] */
0x02060015, /* y */
0x02070056, /* 102nd */
0x0208001a, /* [ */
0x02090042, /* F8 */
{ 0x03, 0x01, 0x29 }, /* grave */
{ 0x03, 0x02, 0x3c }, /* F2 */
{ 0x03, 0x03, 0x06 }, /* 5 */
{ 0x03, 0x04, 0x3f }, /* F5 */
{ 0x03, 0x06, 0x07 }, /* 6 */
{ 0x03, 0x08, 0x0c }, /* - */
{ 0x03, 0x0b, 0x2b }, /* \ */
0x03010029, /* grave */
0x0302003c, /* F2 */
0x03030006, /* 5 */
0x0304003f, /* F5 */
0x03060007, /* 6 */
0x0308000c, /* - */
0x030b002b, /* \ */
{ 0x04, 0x00, 0x61 }, /* rctrl */
{ 0x04, 0x01, 0x1e }, /* a */
{ 0x04, 0x02, 0x20 }, /* d */
{ 0x04, 0x03, 0x21 }, /* f */
{ 0x04, 0x04, 0x1f }, /* s */
{ 0x04, 0x05, 0x25 }, /* k */
{ 0x04, 0x06, 0x24 }, /* j */
{ 0x04, 0x08, 0x27 }, /* ; */
{ 0x04, 0x09, 0x26 }, /* l */
{ 0x04, 0x0a, 0x2b }, /* \ */
{ 0x04, 0x0b, 0x1c }, /* enter */
0x04000061, /* rctrl */
0x0401001e, /* a */
0x04020020, /* d */
0x04030021, /* f */
0x0404001f, /* s */
0x04050025, /* k */
0x04060024, /* j */
0x04080027, /* ; */
0x04090026, /* l */
0x040a002b, /* \ */
0x040b001c, /* enter */
{ 0x05, 0x01, 0x2c }, /* z */
{ 0x05, 0x02, 0x2e }, /* c */
{ 0x05, 0x03, 0x2f }, /* v */
{ 0x05, 0x04, 0x2d }, /* x */
{ 0x05, 0x05, 0x33 }, /* , */
{ 0x05, 0x06, 0x32 }, /* m */
{ 0x05, 0x07, 0x2a }, /* lsh */
{ 0x05, 0x08, 0x35 }, /* / */
{ 0x05, 0x09, 0x34 }, /* . */
{ 0x05, 0x0B, 0x39 }, /* space */
0x0501002c, /* z */
0x0502002e, /* c */
0x0503002f, /* v */
0x0504002d, /* x */
0x05050033, /* , */
0x05060032, /* m */
0x0507002a, /* lsh */
0x05080035, /* / */
0x05090034, /* . */
0x050B0039, /* space */
{ 0x06, 0x01, 0x02 }, /* 1 */
{ 0x06, 0x02, 0x04 }, /* 3 */
{ 0x06, 0x03, 0x05 }, /* 4 */
{ 0x06, 0x04, 0x03 }, /* 2 */
{ 0x06, 0x05, 0x09 }, /* 8 */
{ 0x06, 0x06, 0x08 }, /* 7 */
{ 0x06, 0x08, 0x0b }, /* 0 */
{ 0x06, 0x09, 0x0a }, /* 9 */
{ 0x06, 0x0a, 0x38 }, /* lalt */
{ 0x06, 0x0b, 0x64 }, /* down */
{ 0x06, 0x0c, 0x62 }, /* right */
0x06010002, /* 1 */
0x06020004, /* 3 */
0x06030005, /* 4 */
0x06040003, /* 2 */
0x06050009, /* 8 */
0x06060008, /* 7 */
0x0608000b, /* 0 */
0x0609000a, /* 9 */
0x060a0038, /* lalt */
0x060b0064, /* down */
0x060c0062, /* right */
{ 0x07, 0x01, 0x10 }, /* q */
{ 0x07, 0x02, 0x12 }, /* e */
{ 0x07, 0x03, 0x13 }, /* r */
{ 0x07, 0x04, 0x11 }, /* w */
{ 0x07, 0x05, 0x17 }, /* i */
{ 0x07, 0x06, 0x16 }, /* u */
{ 0x07, 0x07, 0x36 }, /* rsh */
{ 0x07, 0x08, 0x19 }, /* p */
{ 0x07, 0x09, 0x18 }, /* o */
{ 0x07, 0x0b, 0x5F }, /* up */
{ 0x07, 0x0c, 0x61 }, /* left */
0x07010010, /* q */
0x07020012, /* e */
0x07030013, /* r */
0x07040011, /* w */
0x07050017, /* i */
0x07060016, /* u */
0x07070036, /* rsh */
0x07080019, /* p */
0x07090018, /* o */
0x070b005F, /* up */
0x070c0061, /* left */
};

View File

@ -59,9 +59,10 @@
};
keyboard-controller {
compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>;
keypad,num-columns = <13>;
compatible = "google,mkbp-keyb";
google,key-rows = <8>;
google,key-columns = <13>;
freebsd,intr-gpio = <146>;
};
};

View File

@ -59,9 +59,10 @@
};
keyboard-controller {
compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>;
keypad,num-columns = <13>;
compatible = "google,mkbp-keyb";
google,key-rows = <8>;
google,key-columns = <13>;
freebsd,intr-gpio = <146>;
};
};