diff options
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 40244d4ce0f1..cbb93669d1ce 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -221,6 +221,7 @@ struct atkbd { | |||
221 | unsigned long xl_bit; | 221 | unsigned long xl_bit; |
222 | unsigned int last; | 222 | unsigned int last; |
223 | unsigned long time; | 223 | unsigned long time; |
224 | unsigned long err_count; | ||
224 | 225 | ||
225 | struct work_struct event_work; | 226 | struct work_struct event_work; |
226 | struct mutex event_mutex; | 227 | struct mutex event_mutex; |
@@ -234,11 +235,13 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t | |||
234 | #define ATKBD_DEFINE_ATTR(_name) \ | 235 | #define ATKBD_DEFINE_ATTR(_name) \ |
235 | static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ | 236 | static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ |
236 | static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \ | 237 | static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \ |
237 | static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \ | 238 | static ssize_t atkbd_do_show_##_name(struct device *d, \ |
239 | struct device_attribute *attr, char *b) \ | ||
238 | { \ | 240 | { \ |
239 | return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ | 241 | return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ |
240 | } \ | 242 | } \ |
241 | static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s) \ | 243 | static ssize_t atkbd_do_set_##_name(struct device *d, \ |
244 | struct device_attribute *attr, const char *b, size_t s) \ | ||
242 | { \ | 245 | { \ |
243 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ | 246 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ |
244 | } \ | 247 | } \ |
@@ -251,6 +254,32 @@ ATKBD_DEFINE_ATTR(set); | |||
251 | ATKBD_DEFINE_ATTR(softrepeat); | 254 | ATKBD_DEFINE_ATTR(softrepeat); |
252 | ATKBD_DEFINE_ATTR(softraw); | 255 | ATKBD_DEFINE_ATTR(softraw); |
253 | 256 | ||
257 | #define ATKBD_DEFINE_RO_ATTR(_name) \ | ||
258 | static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ | ||
259 | static ssize_t atkbd_do_show_##_name(struct device *d, \ | ||
260 | struct device_attribute *attr, char *b) \ | ||
261 | { \ | ||
262 | return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ | ||
263 | } \ | ||
264 | static struct device_attribute atkbd_attr_##_name = \ | ||
265 | __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL); | ||
266 | |||
267 | ATKBD_DEFINE_RO_ATTR(err_count); | ||
268 | |||
269 | static struct attribute *atkbd_attributes[] = { | ||
270 | &atkbd_attr_extra.attr, | ||
271 | &atkbd_attr_scroll.attr, | ||
272 | &atkbd_attr_set.attr, | ||
273 | &atkbd_attr_softrepeat.attr, | ||
274 | &atkbd_attr_softraw.attr, | ||
275 | &atkbd_attr_err_count.attr, | ||
276 | NULL | ||
277 | }; | ||
278 | |||
279 | static struct attribute_group atkbd_attribute_group = { | ||
280 | .attrs = atkbd_attributes, | ||
281 | }; | ||
282 | |||
254 | static const unsigned int xl_table[] = { | 283 | static const unsigned int xl_table[] = { |
255 | ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK, | 284 | ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK, |
256 | ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL, | 285 | ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL, |
@@ -318,7 +347,7 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code | |||
318 | */ | 347 | */ |
319 | 348 | ||
320 | static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | 349 | static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, |
321 | unsigned int flags, struct pt_regs *regs) | 350 | unsigned int flags) |
322 | { | 351 | { |
323 | struct atkbd *atkbd = serio_get_drvdata(serio); | 352 | struct atkbd *atkbd = serio_get_drvdata(serio); |
324 | struct input_dev *dev = atkbd->dev; | 353 | struct input_dev *dev = atkbd->dev; |
@@ -396,7 +425,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
396 | add_release_event = 1; | 425 | add_release_event = 1; |
397 | break; | 426 | break; |
398 | case ATKBD_RET_ERR: | 427 | case ATKBD_RET_ERR: |
428 | atkbd->err_count++; | ||
429 | #ifdef ATKBD_DEBUG | ||
399 | printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); | 430 | printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); |
431 | #endif | ||
400 | goto out; | 432 | goto out; |
401 | } | 433 | } |
402 | 434 | ||
@@ -458,7 +490,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
458 | atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; | 490 | atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; |
459 | } | 491 | } |
460 | 492 | ||
461 | input_regs(dev, regs); | ||
462 | input_event(dev, EV_KEY, keycode, value); | 493 | input_event(dev, EV_KEY, keycode, value); |
463 | input_sync(dev); | 494 | input_sync(dev); |
464 | 495 | ||
@@ -469,7 +500,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
469 | } | 500 | } |
470 | 501 | ||
471 | if (atkbd->scroll) { | 502 | if (atkbd->scroll) { |
472 | input_regs(dev, regs); | ||
473 | if (click != -1) | 503 | if (click != -1) |
474 | input_report_key(dev, BTN_MIDDLE, click); | 504 | input_report_key(dev, BTN_MIDDLE, click); |
475 | input_report_rel(dev, REL_WHEEL, scroll); | 505 | input_report_rel(dev, REL_WHEEL, scroll); |
@@ -788,12 +818,7 @@ static void atkbd_disconnect(struct serio *serio) | |||
788 | synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */ | 818 | synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */ |
789 | flush_scheduled_work(); | 819 | flush_scheduled_work(); |
790 | 820 | ||
791 | device_remove_file(&serio->dev, &atkbd_attr_extra); | 821 | sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); |
792 | device_remove_file(&serio->dev, &atkbd_attr_scroll); | ||
793 | device_remove_file(&serio->dev, &atkbd_attr_set); | ||
794 | device_remove_file(&serio->dev, &atkbd_attr_softrepeat); | ||
795 | device_remove_file(&serio->dev, &atkbd_attr_softraw); | ||
796 | |||
797 | input_unregister_device(atkbd->dev); | 822 | input_unregister_device(atkbd->dev); |
798 | serio_close(serio); | 823 | serio_close(serio); |
799 | serio_set_drvdata(serio, NULL); | 824 | serio_set_drvdata(serio, NULL); |
@@ -963,11 +988,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
963 | atkbd_set_keycode_table(atkbd); | 988 | atkbd_set_keycode_table(atkbd); |
964 | atkbd_set_device_attrs(atkbd); | 989 | atkbd_set_device_attrs(atkbd); |
965 | 990 | ||
966 | device_create_file(&serio->dev, &atkbd_attr_extra); | 991 | sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); |
967 | device_create_file(&serio->dev, &atkbd_attr_scroll); | ||
968 | device_create_file(&serio->dev, &atkbd_attr_set); | ||
969 | device_create_file(&serio->dev, &atkbd_attr_softrepeat); | ||
970 | device_create_file(&serio->dev, &atkbd_attr_softraw); | ||
971 | 992 | ||
972 | atkbd_enable(atkbd); | 993 | atkbd_enable(atkbd); |
973 | 994 | ||
@@ -1261,6 +1282,11 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co | |||
1261 | return count; | 1282 | return count; |
1262 | } | 1283 | } |
1263 | 1284 | ||
1285 | static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) | ||
1286 | { | ||
1287 | return sprintf(buf, "%lu\n", atkbd->err_count); | ||
1288 | } | ||
1289 | |||
1264 | 1290 | ||
1265 | static int __init atkbd_init(void) | 1291 | static int __init atkbd_init(void) |
1266 | { | 1292 | { |