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;
}

linux keypad driver相关推荐

  1. 终于知道为什么NVIDIA的linux驱动这么烂了,一波官方文档告诉你:Linux GPU Driver Developer’s Guide

    还记得Linus在记者会上那句话吗? so,NVIDIA, F**k you! https://www.kernel.org/doc/html/latest/gpu/index.html Linux ...

  2. [Linux Audio Driver] Qualcomm平台音频GMS认证器件要求

    从GMS测试常见的fail项来明确其器件要求,常见的fail测试项主要是以下三个: 后面是分析,要看结论的话直接拉到文末: 一:Audio Frequency Speaker Test 此测试使用外部 ...

  3. [Linux Audio Driver] SM6350平台音频bring up ( 一 )

    0. 背景 这个是高通5G平台,音频的内容改的比较多,比较直接的是platform.c就直接移动到vendor了:目前 高通那边的趋势还是把音频逐渐从kernel剥离,android 7/androi ...

  4. Linux SDIO WIFI Marvell8801/Marvell88w8801(六) --- Marvell Linux Wi-Fi driver介绍-WIFI插入卡槽内发生的事情

    代码工程的GITHUB连接:点进进入GITHUB仓库 https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi ...

  5. Linux SDIO WIFI Marvell8801/Marvell88w8801(八) --- Marvell Linux Wi-Fi driver 对接芯片上行下行接口介绍

    代码工程的GITHUB连接:点进进入GITHUB仓库 https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi ...

  6. Linux NVMe Driver学习笔记之8:IO SQ/CQ的创建过程

    这篇文章紧接上回分解,在nvme_probe函数的最后一步调用nvme_reset_work进行reset操作,nvme_reset_work的主要工作可以概括如下几个步骤: 进入nvme_reset ...

  7. Linux Joystick driver v2.0.0

    如果想评论或更新本文的内容,请直接联系原文档的维护者. 如果你使用英文交流有困难的话,也可以向中文版维护者求助. 如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者. 中文版维护者: 姚家珺Ar ...

  8. Linux中SDIO命令,linux device driver之sdio驱动编程分享

    linux device driver之sdio驱动编程分享 闯客网 • 2018-12-19 • 技术交流 [p=26, null, left]先谈谈如何写linux驱动:[/p]- 在驱动模块初始 ...

  9. [Linux Audio Driver] Android 10 machine driver probe函数分析

    0. 背景 平台:Qualcomm 5G SM6350.android10.kernel version: msm-4.19. 本文重点分析machine driver里面的msm_asoc_mach ...

最新文章

  1. 【JAVA语法】03Java-继承性
  2. APP功能需求第一版
  3. MySQL——数据库的增删改操作
  4. 从零开始小说 html,从零开始的HTML生活
  5. 使用结构体的形式使一个函数返回多个数据
  6. phpquery类php,一个基于phpQuery的php通用采集类分享
  7. 修改结构体中成员的值
  8. jdk 安装_Linux入门之Linux CentOS安装jdk
  9. eclipse分级,分级列表显示 - bieshixuan的个人博客 - OSCHINA - 中文开源技术交流社区...
  10. 爬虫插件-XPath Helper下载与安装
  11. ScrollView滑动控制
  12. Web前端---HTML+CSS+JS实现的圣诞抓礼物小游戏
  13. python加载mnist数据集
  14. Android的当前应用启动第三方应用(跨软件启动页面)
  15. 办公软件是计算机吗,什么是办公软件_IT /计算机_资料
  16. 计算机c盘用户爆满,电脑C盘又爆满了?这招让你一键清除十几G内存
  17. Html+Css 3D旋转立方体
  18. 代理服务器和IP加速器之间有什么关系?
  19. jupyter扩展插件Nbextensions使用
  20. Linux 文件系统与日志分析

热门文章

  1. CSS进阶(3)- 布局
  2. 8.15.NOIP2019模拟赛总结——2019暑假篇
  3. nodejs下上传文件formidable、multer、body-parser的区别
  4. npm报错npm ERR code ELIFECYCLE
  5. 一文通关苦涩难懂的Java泛型
  6. SAP ABAP 基础知识
  7. 图像数据增强2_albumentation 标注框同时修改(VOC、YOLO)
  8. 更好的确保企业数据安全,华为云数据灾备解决方案更便捷
  9. matlab画图三角号,MATLAB画图技巧——在字母上方添加倒三角
  10. Drupal网站系统的应用