pcf8574_keypad.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Driver for a keypad w/16 buttons connected to a PCF8574 I2C I/O expander
  4. *
  5. * Copyright 2005-2008 Analog Devices Inc.
  6. */
  7. #include <linux/module.h>
  8. #include <linux/input.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/i2c.h>
  11. #include <linux/slab.h>
  12. #include <linux/workqueue.h>
  13. #define DRV_NAME "pcf8574_keypad"
  14. static const unsigned char pcf8574_kp_btncode[] = {
  15. [0] = KEY_RESERVED,
  16. [1] = KEY_ENTER,
  17. [2] = KEY_BACKSLASH,
  18. [3] = KEY_0,
  19. [4] = KEY_RIGHTBRACE,
  20. [5] = KEY_C,
  21. [6] = KEY_9,
  22. [7] = KEY_8,
  23. [8] = KEY_7,
  24. [9] = KEY_B,
  25. [10] = KEY_6,
  26. [11] = KEY_5,
  27. [12] = KEY_4,
  28. [13] = KEY_A,
  29. [14] = KEY_3,
  30. [15] = KEY_2,
  31. [16] = KEY_1
  32. };
  33. struct kp_data {
  34. unsigned short btncode[ARRAY_SIZE(pcf8574_kp_btncode)];
  35. struct input_dev *idev;
  36. struct i2c_client *client;
  37. char name[64];
  38. char phys[32];
  39. unsigned char laststate;
  40. };
  41. static short read_state(struct kp_data *lp)
  42. {
  43. unsigned char x, y, a, b;
  44. i2c_smbus_write_byte(lp->client, 240);
  45. x = 0xF & (~(i2c_smbus_read_byte(lp->client) >> 4));
  46. i2c_smbus_write_byte(lp->client, 15);
  47. y = 0xF & (~i2c_smbus_read_byte(lp->client));
  48. for (a = 0; x > 0; a++)
  49. x = x >> 1;
  50. for (b = 0; y > 0; b++)
  51. y = y >> 1;
  52. return ((a - 1) * 4) + b;
  53. }
  54. static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
  55. {
  56. struct kp_data *lp = dev_id;
  57. unsigned char nextstate = read_state(lp);
  58. if (lp->laststate != nextstate) {
  59. int key_down = nextstate < ARRAY_SIZE(lp->btncode);
  60. unsigned short keycode = key_down ?
  61. lp->btncode[nextstate] : lp->btncode[lp->laststate];
  62. input_report_key(lp->idev, keycode, key_down);
  63. input_sync(lp->idev);
  64. lp->laststate = nextstate;
  65. }
  66. return IRQ_HANDLED;
  67. }
  68. static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id)
  69. {
  70. int i, ret;
  71. struct input_dev *idev;
  72. struct kp_data *lp;
  73. if (i2c_smbus_write_byte(client, 240) < 0) {
  74. dev_err(&client->dev, "probe: write fail\n");
  75. return -ENODEV;
  76. }
  77. lp = kzalloc(sizeof(*lp), GFP_KERNEL);
  78. if (!lp)
  79. return -ENOMEM;
  80. idev = input_allocate_device();
  81. if (!idev) {
  82. dev_err(&client->dev, "Can't allocate input device\n");
  83. ret = -ENOMEM;
  84. goto fail_allocate;
  85. }
  86. lp->idev = idev;
  87. lp->client = client;
  88. idev->evbit[0] = BIT_MASK(EV_KEY);
  89. idev->keycode = lp->btncode;
  90. idev->keycodesize = sizeof(lp->btncode[0]);
  91. idev->keycodemax = ARRAY_SIZE(lp->btncode);
  92. for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) {
  93. if (lp->btncode[i] <= KEY_MAX) {
  94. lp->btncode[i] = pcf8574_kp_btncode[i];
  95. __set_bit(lp->btncode[i], idev->keybit);
  96. }
  97. }
  98. __clear_bit(KEY_RESERVED, idev->keybit);
  99. sprintf(lp->name, DRV_NAME);
  100. sprintf(lp->phys, "kp_data/input0");
  101. idev->name = lp->name;
  102. idev->phys = lp->phys;
  103. idev->id.bustype = BUS_I2C;
  104. idev->id.vendor = 0x0001;
  105. idev->id.product = 0x0001;
  106. idev->id.version = 0x0100;
  107. lp->laststate = read_state(lp);
  108. ret = request_threaded_irq(client->irq, NULL, pcf8574_kp_irq_handler,
  109. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  110. DRV_NAME, lp);
  111. if (ret) {
  112. dev_err(&client->dev, "IRQ %d is not free\n", client->irq);
  113. goto fail_free_device;
  114. }
  115. ret = input_register_device(idev);
  116. if (ret) {
  117. dev_err(&client->dev, "input_register_device() failed\n");
  118. goto fail_free_irq;
  119. }
  120. i2c_set_clientdata(client, lp);
  121. return 0;
  122. fail_free_irq:
  123. free_irq(client->irq, lp);
  124. fail_free_device:
  125. input_free_device(idev);
  126. fail_allocate:
  127. kfree(lp);
  128. return ret;
  129. }
  130. static void pcf8574_kp_remove(struct i2c_client *client)
  131. {
  132. struct kp_data *lp = i2c_get_clientdata(client);
  133. free_irq(client->irq, lp);
  134. input_unregister_device(lp->idev);
  135. kfree(lp);
  136. }
  137. #ifdef CONFIG_PM
  138. static int pcf8574_kp_resume(struct device *dev)
  139. {
  140. struct i2c_client *client = to_i2c_client(dev);
  141. enable_irq(client->irq);
  142. return 0;
  143. }
  144. static int pcf8574_kp_suspend(struct device *dev)
  145. {
  146. struct i2c_client *client = to_i2c_client(dev);
  147. disable_irq(client->irq);
  148. return 0;
  149. }
  150. static const struct dev_pm_ops pcf8574_kp_pm_ops = {
  151. .suspend = pcf8574_kp_suspend,
  152. .resume = pcf8574_kp_resume,
  153. };
  154. #else
  155. # define pcf8574_kp_resume NULL
  156. # define pcf8574_kp_suspend NULL
  157. #endif
  158. static const struct i2c_device_id pcf8574_kp_id[] = {
  159. { DRV_NAME, 0 },
  160. { }
  161. };
  162. MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id);
  163. static struct i2c_driver pcf8574_kp_driver = {
  164. .driver = {
  165. .name = DRV_NAME,
  166. #ifdef CONFIG_PM
  167. .pm = &pcf8574_kp_pm_ops,
  168. #endif
  169. },
  170. .probe = pcf8574_kp_probe,
  171. .remove = pcf8574_kp_remove,
  172. .id_table = pcf8574_kp_id,
  173. };
  174. module_i2c_driver(pcf8574_kp_driver);
  175. MODULE_AUTHOR("Michael Hennerich");
  176. MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574");
  177. MODULE_LICENSE("GPL");