xref: /openbmc/linux/drivers/input/matrix-keymap.c (revision 33a03aad)
1 /*
2  * Helpers for matrix keyboard bindings
3  *
4  * Copyright (C) 2012 Google, Inc
5  *
6  * Author:
7  *	Olof Johansson <olof@lixom.net>
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  */
19 
20 #include <linux/device.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/input.h>
24 #include <linux/of.h>
25 #include <linux/export.h>
26 #include <linux/input/matrix_keypad.h>
27 
28 static bool matrix_keypad_map_key(struct input_dev *input_dev,
29 				  unsigned int rows, unsigned int cols,
30 				  unsigned int row_shift, unsigned int key)
31 {
32 	unsigned short *keymap = input_dev->keycode;
33 	unsigned int row = KEY_ROW(key);
34 	unsigned int col = KEY_COL(key);
35 	unsigned short code = KEY_VAL(key);
36 
37 	if (row >= rows || col >= cols) {
38 		dev_err(input_dev->dev.parent,
39 			"%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
40 			__func__, key, row, col, rows, cols);
41 		return false;
42 	}
43 
44 	keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
45 	__set_bit(code, input_dev->keybit);
46 
47 	return true;
48 }
49 
50 #ifdef CONFIG_OF
51 static int matrix_keypad_parse_of_keymap(const char *propname,
52 					 unsigned int rows, unsigned int cols,
53 					 struct input_dev *input_dev)
54 {
55 	struct device *dev = input_dev->dev.parent;
56 	struct device_node *np = dev->of_node;
57 	unsigned int row_shift = get_count_order(cols);
58 	unsigned int max_keys = rows << row_shift;
59 	unsigned int proplen, i, size;
60 	const __be32 *prop;
61 
62 	if (!np)
63 		return -ENOENT;
64 
65 	if (!propname)
66 		propname = "linux,keymap";
67 
68 	prop = of_get_property(np, propname, &proplen);
69 	if (!prop) {
70 		dev_err(dev, "OF: %s property not defined in %s\n",
71 			propname, np->full_name);
72 		return -ENOENT;
73 	}
74 
75 	if (proplen % sizeof(u32)) {
76 		dev_err(dev, "OF: Malformed keycode property %s in %s\n",
77 			propname, np->full_name);
78 		return -EINVAL;
79 	}
80 
81 	size = proplen / sizeof(u32);
82 	if (size > max_keys) {
83 		dev_err(dev, "OF: %s size overflow\n", propname);
84 		return -EINVAL;
85 	}
86 
87 	for (i = 0; i < size; i++) {
88 		unsigned int key = be32_to_cpup(prop + i);
89 
90 		if (!matrix_keypad_map_key(input_dev, rows, cols,
91 					   row_shift, key))
92 			return -EINVAL;
93 	}
94 
95 	return 0;
96 }
97 #else
98 static int matrix_keypad_parse_of_keymap(const char *propname,
99 					 unsigned int rows, unsigned int cols,
100 					 struct input_dev *input_dev)
101 {
102 	return -ENOSYS;
103 }
104 #endif
105 
106 /**
107  * matrix_keypad_build_keymap - convert platform keymap into matrix keymap
108  * @keymap_data: keymap supplied by the platform code
109  * @keymap_name: name of device tree property containing keymap (if device
110  *	tree support is enabled).
111  * @rows: number of rows in target keymap array
112  * @cols: number of cols in target keymap array
113  * @keymap: expanded version of keymap that is suitable for use by
114  * matrix keyboard driver
115  * @input_dev: input devices for which we are setting up the keymap
116  *
117  * This function converts platform keymap (encoded with KEY() macro) into
118  * an array of keycodes that is suitable for using in a standard matrix
119  * keyboard driver that uses row and col as indices.
120  *
121  * If @keymap_data is not supplied and device tree support is enabled
122  * it will attempt load the keymap from property specified by @keymap_name
123  * argument (or "linux,keymap" if @keymap_name is %NULL).
124  *
125  * Callers are expected to set up input_dev->dev.parent before calling this
126  * function.
127  */
128 int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
129 			       const char *keymap_name,
130 			       unsigned int rows, unsigned int cols,
131 			       unsigned short *keymap,
132 			       struct input_dev *input_dev)
133 {
134 	unsigned int row_shift = get_count_order(cols);
135 	int i;
136 	int error;
137 
138 	input_dev->keycode = keymap;
139 	input_dev->keycodesize = sizeof(*keymap);
140 	input_dev->keycodemax = rows << row_shift;
141 
142 	__set_bit(EV_KEY, input_dev->evbit);
143 
144 	if (keymap_data) {
145 		for (i = 0; i < keymap_data->keymap_size; i++) {
146 			unsigned int key = keymap_data->keymap[i];
147 
148 			if (!matrix_keypad_map_key(input_dev, rows, cols,
149 						   row_shift, key))
150 				return -EINVAL;
151 		}
152 	} else {
153 		error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols,
154 						      input_dev);
155 		if (error)
156 			return error;
157 	}
158 
159 	__clear_bit(KEY_RESERVED, input_dev->keybit);
160 
161 	return 0;
162 }
163 EXPORT_SYMBOL(matrix_keypad_build_keymap);
164