linux keypad driver
来源:互联网 发布:约瑟夫环 递归算法 编辑:程序博客网 时间:2024/06/06 12:44
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;}
0 0
- linux keypad driver
- linux keypad driver
- gpio matrix keypad linux driver
- keypad driver
- keypad driver
- keypad driver
- MTK keypad driver
- linux curses库的keypad模式
- mx53 linux gpio 模拟matrix keypad
- Analysis of Keypad Driver of Marvell (Marvell PXA310键盘驱动代码分析)
- Linux driver
- linux driver
- Linux Driver
- linux driver
- linux kernel, driver, network driver
- Optimal Keypad
- Numeric Keypad
- keypad 错误
- 黑马程序员--手机类的例子
- 笨笨VC调试串口程序
- 由freemarker毫秒级时间谈固定日期格式
- css3兼容性问题归纳
- IMap.FeatureSelection方法获取Feature的属性信息
- linux keypad driver
- [LeetCode] Set Matrix Zeroes (!!!!时间空间复杂度)
- Spring mvc学习笔记
- Coprime
- The Procedure of AD9250 Parameter Configuration(AD9250 参数配置 + xilinx K7)
- 递推 ACdream1420 High Speed Trains
- Python数据库ORM SQLAlchemy 0.7学习笔记(1) 概要
- fibonacci数列
- secondary index