aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDoug Anderson <dianders@chromium.org>2013-12-29 19:52:46 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-12-31 13:45:29 -0500
commit64757eba624422f8d30e4248f6f10719ac8b2311 (patch)
tree85c86d0de409b978da2c94a6bde098c8d976d279 /drivers/input
parentb38b4b4f8c4aa8e29f7cf8af2716fb3f9c867207 (diff)
Input: cros_ec_keyb - fix problems with backslash
The driver can't deal with two entries its keymap having the same keycode. When this happens it will get confused about whether the key is down or up and will cause some screwy behavior. We need to have two entries for KEY_BACKSLASH to handle US and UK keyboards. Specifically: * On the US keyboard the backslash key (above enter) is r3 c11 and is supposed to be reported as BACKSLASH. * On the UK keyboard the # key (left of enter) is r4 c10 and is supposed to be reported as BACKSLASH. * On the UK keyboard the \ key (left of Z) is r2 c7 and is supposed to be reported as KEY_102ND. Note that both keyboards (US and UK) have only one physical backslash key so the constraint that each physical key should have its own keycode still stands. Signed-off-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 7e8b0a52af25..408379669d3c 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -38,6 +38,7 @@
38 * @row_shift: log2 or number of rows, rounded up 38 * @row_shift: log2 or number of rows, rounded up
39 * @keymap_data: Matrix keymap data used to convert to keyscan values 39 * @keymap_data: Matrix keymap data used to convert to keyscan values
40 * @ghost_filter: true to enable the matrix key-ghosting filter 40 * @ghost_filter: true to enable the matrix key-ghosting filter
41 * @old_kb_state: bitmap of keys pressed last scan
41 * @dev: Device pointer 42 * @dev: Device pointer
42 * @idev: Input device 43 * @idev: Input device
43 * @ec: Top level ChromeOS device to use to talk to EC 44 * @ec: Top level ChromeOS device to use to talk to EC
@@ -49,6 +50,7 @@ struct cros_ec_keyb {
49 int row_shift; 50 int row_shift;
50 const struct matrix_keymap_data *keymap_data; 51 const struct matrix_keymap_data *keymap_data;
51 bool ghost_filter; 52 bool ghost_filter;
53 uint8_t *old_kb_state;
52 54
53 struct device *dev; 55 struct device *dev;
54 struct input_dev *idev; 56 struct input_dev *idev;
@@ -135,6 +137,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
135 struct input_dev *idev = ckdev->idev; 137 struct input_dev *idev = ckdev->idev;
136 int col, row; 138 int col, row;
137 int new_state; 139 int new_state;
140 int old_state;
138 int num_cols; 141 int num_cols;
139 142
140 num_cols = len; 143 num_cols = len;
@@ -153,18 +156,19 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
153 for (row = 0; row < ckdev->rows; row++) { 156 for (row = 0; row < ckdev->rows; row++) {
154 int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); 157 int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
155 const unsigned short *keycodes = idev->keycode; 158 const unsigned short *keycodes = idev->keycode;
156 int code;
157 159
158 code = keycodes[pos];
159 new_state = kb_state[col] & (1 << row); 160 new_state = kb_state[col] & (1 << row);
160 if (!!new_state != test_bit(code, idev->key)) { 161 old_state = ckdev->old_kb_state[col] & (1 << row);
162 if (new_state != old_state) {
161 dev_dbg(ckdev->dev, 163 dev_dbg(ckdev->dev,
162 "changed: [r%d c%d]: byte %02x\n", 164 "changed: [r%d c%d]: byte %02x\n",
163 row, col, new_state); 165 row, col, new_state);
164 166
165 input_report_key(idev, code, new_state); 167 input_report_key(idev, keycodes[pos],
168 new_state);
166 } 169 }
167 } 170 }
171 ckdev->old_kb_state[col] = kb_state[col];
168 } 172 }
169 input_sync(ckdev->idev); 173 input_sync(ckdev->idev);
170} 174}
@@ -226,6 +230,9 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
226 &ckdev->cols); 230 &ckdev->cols);
227 if (err) 231 if (err)
228 return err; 232 return err;
233 ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
234 if (!ckdev->old_kb_state)
235 return -ENOMEM;
229 236
230 idev = devm_input_allocate_device(&pdev->dev); 237 idev = devm_input_allocate_device(&pdev->dev);
231 if (!idev) 238 if (!idev)