大家好,又见面了,我是你们的朋友全栈君。
1、DTS文件
&keypad {
keypad,num-rows = <8>;
keypad,num-columns = <8>;
linux,keymap = <0x00000012 /* KEY_E */
0x00010013 /* KEY_R */
0x00020014 /* KEY_T */
0x00030066 /* KEY_HOME */
0x0004003f /* KEY_F5 */
0x000500f0 /* KEY_UNKNOWN */
0x00060017 /* KEY_I */
0x0007002a /* KEY_LEFTSHIFT */
0x01000020 /* KEY_D*/
0x01010021 /* KEY_F */
0x01020022 /* KEY_G */
0x010300e7 /* KEY_SEND */
0x01040040 /* KEY_F6 */
0x010500f0 /* KEY_UNKNOWN */
0x01060025 /* KEY_K */
0x0107001c /* KEY_ENTER */
0x0200002d /* KEY_X */
0x0201002e /* KEY_C */
0x0202002f /* KEY_V */
0x0203006b /* KEY_END */
0x02040041 /* KEY_F7 */
0x020500f0 /* KEY_UNKNOWN */
0x02060034 /* KEY_DOT */
0x0207003a /* KEY_CAPSLOCK */
0x0300002c /* KEY_Z */
0x0301004e /* KEY_KPLUS */
0x03020030 /* KEY_B */
0x0303003b /* KEY_F1 */
0x03040042 /* KEY_F8 */
0x030500f0 /* KEY_UNKNOWN */
0x03060018 /* KEY_O */
0x03070039 /* KEY_SPACE */
0x04000011 /* KEY_W */
0x04010015 /* KEY_Y */
0x04020016 /* KEY_U */
0x0403003c /* KEY_F2 */
0x04040073 /* KEY_VOLUMEUP */
0x040500f0 /* KEY_UNKNOWN */
0x04060026 /* KEY_L */
0x04070069 /* KEY_LEFT */
0x0500001f /* KEY_S */
0x05010023 /* KEY_H */
0x05020024 /* KEY_J */
0x0503003d /* KEY_F3 */
0x05040043 /* KEY_F9 */
0x05050072 /* KEY_VOLUMEDOWN */
0x05060032 /* KEY_M */
0x0507006a /* KEY_RIGHT */
0x06000010 /* KEY_Q */
0x0601001e /* KEY_A */
0x06020031 /* KEY_N */
0x0603009e /* KEY_BACK */
0x0604000e /* KEY_BACKSPACE */
0x060500f0 /* KEY_UNKNOWN */
0x06060019 /* KEY_P */
0x06070067 /* KEY_UP */
0x07000094 /* KEY_PROG1 */
0x07010095 /* KEY_PROG2 */
0x070200ca /* KEY_PROG3 */
0x070300cb /* KEY_PROG4 */
0x0704003e /* KEY_F4 */
0x070500f0 /* KEY_UNKNOWN */
0x07060160 /* KEY_OK */
0x0707006c>; /* KEY_DOWN */
linux,input-no-autorepeat;
};
总行列数目,num-rows最大行数目,num-columns最大列数目。
0x00030066 /* KEY_HOME*/
00行,03列,键值0x66即HOME建
2、驱动
路径 linux\drivers\input\keybord\
2、1 probe
static int omap4_keypad_probe(struct platform_device *pdev)
{
const struct omap4_keypad_platform_data *pdata =
dev_get_platdata(&pdev->dev);
const struct matrix_keymap_data *keymap_data =
pdata ? pdata->keymap_data : NULL;
struct omap4_keypad *keypad_data;
struct input_dev *input_dev;
struct resource *res;
unsigned int max_keys;
int rev;
int irq;
int error;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no base address specified\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (!irq) {
dev_err(&pdev->dev, "no keyboard irq assigned\n");
return -EINVAL;
}
keypad_data = kzalloc(sizeof(struct omap4_keypad), GFP_KERNEL);
if (!keypad_data) {
dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
return -ENOMEM;
}
keypad_data->irq = irq;
if (pdata) {
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
} else {
error = omap4_keypad_parse_dt(&pdev->dev, keypad_data);
if (error)
return error;
}
res = request_mem_region(res->start, resource_size(res), pdev->name);
if (!res) {
dev_err(&pdev->dev, "can't request mem region\n");
error = -EBUSY;
goto err_free_keypad;
}
keypad_data->base = ioremap(res->start, resource_size(res));
if (!keypad_data->base) {
dev_err(&pdev->dev, "can't ioremap mem resource\n");
error = -ENOMEM;
goto err_release_mem;
}
/*
* Enable clocks for the keypad module so that we can read
* revision register.
*/
pm_runtime_enable(&pdev->dev);
error = pm_runtime_get_sync(&pdev->dev);
if (error) {
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
goto err_unmap;
}
rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
rev &= 0x03 << 30;
rev >>= 30;
switch (rev) {
case KBD_REVISION_OMAP4:
keypad_data->reg_offset = 0x00;
keypad_data->irqreg_offset = 0x00;
break;
case KBD_REVISION_OMAP5:
keypad_data->reg_offset = 0x10;
keypad_data->irqreg_offset = 0x0c;
break;
default:
dev_err(&pdev->dev,
"Keypad reports unsupported revision %d", rev);
error = -EINVAL;
goto err_pm_put_sync;
}
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
goto err_pm_put_sync;
}
input_dev->name = pdev->name;
input_dev->dev.parent = &pdev->dev;
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0001;
input_dev->open = omap4_keypad_open;
input_dev->close = omap4_keypad_close;
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
if (!keypad_data->no_autorepeat)
__set_bit(EV_REP, input_dev->evbit);
input_set_drvdata(input_dev, keypad_data);
keypad_data->row_shift = get_count_order(keypad_data->cols);
max_keys = keypad_data->rows << keypad_data->row_shift;
keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]),
GFP_KERNEL);
if (!keypad_data->keymap) {
dev_err(&pdev->dev, "Not enough memory for keymap\n");
error = -ENOMEM;
goto err_free_input;
}
error = matrix_keypad_build_keymap(keymap_data, NULL,
keypad_data->rows, keypad_data->cols,
keypad_data->keymap, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_free_keymap;
}
error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler,
omap4_keypad_irq_thread_fn, 0,
"omap4-keypad", keypad_data);
if (error) {
dev_err(&pdev->dev, "failed to register interrupt\n");
goto err_free_input;
}
device_init_wakeup(&pdev->dev, true);
pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
dev_err(&pdev->dev, "failed to register input device\n");
goto err_pm_disable;
}
platform_set_drvdata(pdev, keypad_data);
return 0;
err_pm_disable:
pm_runtime_disable(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
free_irq(keypad_data->irq, keypad_data);
err_free_keymap:
kfree(keypad_data->keymap);
err_free_input:
input_free_device(input_dev);
err_pm_put_sync:
pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
release_mem_region(res->start, resource_size(res));
err_free_keypad:
kfree(keypad_data);
return error;
}
2、2 parse
static int omap4_keypad_parse_dt(struct device *dev,
struct omap4_keypad *keypad_data)
{
struct device_node *np = dev->of_node;
int err;
err = matrix_keypad_parse_of_params(dev, &keypad_data->rows,
&keypad_data->cols);
if (err)
return err;
if (of_get_property(np, "linux,input-no-autorepeat", NULL))
keypad_data->no_autorepeat = true;
return 0;
}
int matrix_keypad_parse_of_params(struct device *dev,
unsigned int *rows, unsigned int *cols)
{
struct device_node *np = dev->of_node;
if (!np) {
dev_err(dev, "missing DT data");
return -EINVAL;
}
of_property_read_u32(np, "keypad,num-rows", rows);
of_property_read_u32(np, "keypad,num-columns", cols);
if (!*rows || !*cols) {
dev_err(dev, "number of keypad rows/columns not specified\n");
return -EINVAL;
}
return 0;
}
2、3 build keymap
int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
const char *keymap_name,
unsigned int rows, unsigned int cols,
unsigned short *keymap,
struct input_dev *input_dev)
{
unsigned int row_shift = get_count_order(cols);
size_t max_keys = rows << row_shift;
int i;
int error;
if (WARN_ON(!input_dev->dev.parent))
return -EINVAL;
if (!keymap) {
keymap = devm_kzalloc(input_dev->dev.parent,
max_keys * sizeof(*keymap),
GFP_KERNEL);
if (!keymap) {
dev_err(input_dev->dev.parent,
"Unable to allocate memory for keymap");
return -ENOMEM;
}
}
input_dev->keycode = keymap;
input_dev->keycodesize = sizeof(*keymap);
input_dev->keycodemax = max_keys;
__set_bit(EV_KEY, input_dev->evbit);
if (keymap_data) {
for (i = 0; i < keymap_data->keymap_size; i++) {
unsigned int key = keymap_data->keymap[i];
if (!matrix_keypad_map_key(input_dev, rows, cols,
row_shift, key))
return -EINVAL;
}
} else {
error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols,
input_dev);
if (error)
return error;
}
__clear_bit(KEY_RESERVED, input_dev->keybit);
return 0;
}
static int matrix_keypad_parse_of_keymap(const char *propname,
unsigned int rows, unsigned int cols,
struct input_dev *input_dev)
{
struct device *dev = input_dev->dev.parent;
struct device_node *np = dev->of_node;
unsigned int row_shift = get_count_order(cols);
unsigned int max_keys = rows << row_shift;
unsigned int proplen, i, size;
const __be32 *prop;
if (!np)
return -ENOENT;
if (!propname)
propname = "linux,keymap";
prop = of_get_property(np, propname, &proplen);
if (!prop) {
dev_err(dev, "OF: %s property not defined in %s\n",
propname, np->full_name);
return -ENOENT;
}
if (proplen % sizeof(u32)) {
dev_err(dev, "OF: Malformed keycode property %s in %s\n",
propname, np->full_name);
return -EINVAL;
}
size = proplen / sizeof(u32);
if (size > max_keys) {
dev_err(dev, "OF: %s size overflow\n", propname);
return -EINVAL;
}
for (i = 0; i < size; i++) {
unsigned int key = be32_to_cpup(prop + i);
if (!matrix_keypad_map_key(input_dev, rows, cols,
row_shift, key))
return -EINVAL;
}
return 0;
}
static bool matrix_keypad_map_key(struct input_dev *input_dev,
unsigned int rows, unsigned int cols,
unsigned int row_shift, unsigned int key)
{
unsigned short *keymap = input_dev->keycode;
unsigned int row = KEY_ROW(key);
unsigned int col = KEY_COL(key);
unsigned short code = KEY_VAL(key);
if (row >= rows || col >= cols) {
dev_err(input_dev->dev.parent,
"%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
__func__, key, row, col, rows, cols);
return false;
}
keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
__set_bit(code, input_dev->keybit);
return true;
}
2、4 irq
static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
{
struct omap4_keypad *keypad_data = dev_id;
struct input_dev *input_dev = keypad_data->input;
unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
unsigned int col, row, code, changed;
u32 *new_state = (u32 *) key_state;
*new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
*(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
if (!changed)
continue;
for (col = 0; col < keypad_data->cols; col++) {
if (changed & (1 << col)) {
code = MATRIX_SCAN_CODE(row, col,
keypad_data->row_shift);
input_event(input_dev, EV_MSC, MSC_SCAN, code);
input_report_key(input_dev,
keypad_data->keymap[code],
key_state[row] & (1 << col));
}
}
}
input_sync(input_dev);
memcpy(keypad_data->key_state, key_state,
sizeof(keypad_data->key_state));
/* clear pending interrupts */
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
OMAP4_DEF_IRQENABLE_EVENTEN |
OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133118.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...