This source file includes following definitions.
- matrix_keypad_map_key
- matrix_keypad_parse_properties
- matrix_keypad_parse_keymap
- matrix_keypad_build_keymap
1
2
3
4
5
6
7
8
9
10
11 #include <linux/device.h>
12 #include <linux/export.h>
13 #include <linux/gfp.h>
14 #include <linux/input.h>
15 #include <linux/input/matrix_keypad.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/property.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
21
22 static bool matrix_keypad_map_key(struct input_dev *input_dev,
23 unsigned int rows, unsigned int cols,
24 unsigned int row_shift, unsigned int key)
25 {
26 unsigned short *keymap = input_dev->keycode;
27 unsigned int row = KEY_ROW(key);
28 unsigned int col = KEY_COL(key);
29 unsigned short code = KEY_VAL(key);
30
31 if (row >= rows || col >= cols) {
32 dev_err(input_dev->dev.parent,
33 "%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
34 __func__, key, row, col, rows, cols);
35 return false;
36 }
37
38 keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
39 __set_bit(code, input_dev->keybit);
40
41 return true;
42 }
43
44
45
46
47
48
49
50
51
52 int matrix_keypad_parse_properties(struct device *dev,
53 unsigned int *rows, unsigned int *cols)
54 {
55 *rows = *cols = 0;
56
57 device_property_read_u32(dev, "keypad,num-rows", rows);
58 device_property_read_u32(dev, "keypad,num-columns", cols);
59
60 if (!*rows || !*cols) {
61 dev_err(dev, "number of keypad rows/columns not specified\n");
62 return -EINVAL;
63 }
64
65 return 0;
66 }
67 EXPORT_SYMBOL_GPL(matrix_keypad_parse_properties);
68
69 static int matrix_keypad_parse_keymap(const char *propname,
70 unsigned int rows, unsigned int cols,
71 struct input_dev *input_dev)
72 {
73 struct device *dev = input_dev->dev.parent;
74 unsigned int row_shift = get_count_order(cols);
75 unsigned int max_keys = rows << row_shift;
76 u32 *keys;
77 int i;
78 int size;
79 int retval;
80
81 if (!propname)
82 propname = "linux,keymap";
83
84 size = device_property_count_u32(dev, propname);
85 if (size <= 0) {
86 dev_err(dev, "missing or malformed property %s: %d\n",
87 propname, size);
88 return size < 0 ? size : -EINVAL;
89 }
90
91 if (size > max_keys) {
92 dev_err(dev, "%s size overflow (%d vs max %u)\n",
93 propname, size, max_keys);
94 return -EINVAL;
95 }
96
97 keys = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
98 if (!keys)
99 return -ENOMEM;
100
101 retval = device_property_read_u32_array(dev, propname, keys, size);
102 if (retval) {
103 dev_err(dev, "failed to read %s property: %d\n",
104 propname, retval);
105 goto out;
106 }
107
108 for (i = 0; i < size; i++) {
109 if (!matrix_keypad_map_key(input_dev, rows, cols,
110 row_shift, keys[i])) {
111 retval = -EINVAL;
112 goto out;
113 }
114 }
115
116 retval = 0;
117
118 out:
119 kfree(keys);
120 return retval;
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
151 const char *keymap_name,
152 unsigned int rows, unsigned int cols,
153 unsigned short *keymap,
154 struct input_dev *input_dev)
155 {
156 unsigned int row_shift = get_count_order(cols);
157 size_t max_keys = rows << row_shift;
158 int i;
159 int error;
160
161 if (WARN_ON(!input_dev->dev.parent))
162 return -EINVAL;
163
164 if (!keymap) {
165 keymap = devm_kcalloc(input_dev->dev.parent,
166 max_keys, sizeof(*keymap),
167 GFP_KERNEL);
168 if (!keymap) {
169 dev_err(input_dev->dev.parent,
170 "Unable to allocate memory for keymap");
171 return -ENOMEM;
172 }
173 }
174
175 input_dev->keycode = keymap;
176 input_dev->keycodesize = sizeof(*keymap);
177 input_dev->keycodemax = max_keys;
178
179 __set_bit(EV_KEY, input_dev->evbit);
180
181 if (keymap_data) {
182 for (i = 0; i < keymap_data->keymap_size; i++) {
183 unsigned int key = keymap_data->keymap[i];
184
185 if (!matrix_keypad_map_key(input_dev, rows, cols,
186 row_shift, key))
187 return -EINVAL;
188 }
189 } else {
190 error = matrix_keypad_parse_keymap(keymap_name, rows, cols,
191 input_dev);
192 if (error)
193 return error;
194 }
195
196 __clear_bit(KEY_RESERVED, input_dev->keybit);
197
198 return 0;
199 }
200 EXPORT_SYMBOL(matrix_keypad_build_keymap);
201
202 MODULE_LICENSE("GPL");