adafruit-seesaw.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
  4. *
  5. * Driver for Adafruit Mini I2C Gamepad
  6. *
  7. * Based on the work of:
  8. * Oleh Kravchenko (Sparkfun Qwiic Joystick driver)
  9. *
  10. * Datasheet: https://cdn-learn.adafruit.com/downloads/pdf/gamepad-qt.pdf
  11. * Product page: https://www.adafruit.com/product/5743
  12. * Firmware and hardware sources: https://github.com/adafruit/Adafruit_Seesaw
  13. *
  14. * TODO:
  15. * - Add interrupt support
  16. */
  17. #include <linux/unaligned.h>
  18. #include <linux/bits.h>
  19. #include <linux/delay.h>
  20. #include <linux/i2c.h>
  21. #include <linux/input.h>
  22. #include <linux/input/sparse-keymap.h>
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. #define SEESAW_DEVICE_NAME "seesaw-gamepad"
  26. #define SEESAW_ADC_BASE 0x0900
  27. #define SEESAW_GPIO_DIRCLR_BULK 0x0103
  28. #define SEESAW_GPIO_BULK 0x0104
  29. #define SEESAW_GPIO_BULK_SET 0x0105
  30. #define SEESAW_GPIO_PULLENSET 0x010b
  31. #define SEESAW_STATUS_HW_ID 0x0001
  32. #define SEESAW_STATUS_SWRST 0x007f
  33. #define SEESAW_ADC_OFFSET 0x07
  34. #define SEESAW_BUTTON_A 0x05
  35. #define SEESAW_BUTTON_B 0x01
  36. #define SEESAW_BUTTON_X 0x06
  37. #define SEESAW_BUTTON_Y 0x02
  38. #define SEESAW_BUTTON_START 0x10
  39. #define SEESAW_BUTTON_SELECT 0x00
  40. #define SEESAW_ANALOG_X 0x0e
  41. #define SEESAW_ANALOG_Y 0x0f
  42. #define SEESAW_JOYSTICK_MAX_AXIS 1023
  43. #define SEESAW_JOYSTICK_FUZZ 2
  44. #define SEESAW_JOYSTICK_FLAT 4
  45. #define SEESAW_GAMEPAD_POLL_INTERVAL_MS 16
  46. #define SEESAW_GAMEPAD_POLL_MIN 8
  47. #define SEESAW_GAMEPAD_POLL_MAX 32
  48. static const u32 SEESAW_BUTTON_MASK =
  49. BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) |
  50. BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) |
  51. BIT(SEESAW_BUTTON_SELECT);
  52. struct seesaw_gamepad {
  53. struct input_dev *input_dev;
  54. struct i2c_client *i2c_client;
  55. u32 button_state;
  56. };
  57. struct seesaw_data {
  58. u16 x;
  59. u16 y;
  60. u32 button_state;
  61. };
  62. static const struct key_entry seesaw_buttons_new[] = {
  63. { KE_KEY, SEESAW_BUTTON_A, .keycode = BTN_SOUTH },
  64. { KE_KEY, SEESAW_BUTTON_B, .keycode = BTN_EAST },
  65. { KE_KEY, SEESAW_BUTTON_X, .keycode = BTN_NORTH },
  66. { KE_KEY, SEESAW_BUTTON_Y, .keycode = BTN_WEST },
  67. { KE_KEY, SEESAW_BUTTON_START, .keycode = BTN_START },
  68. { KE_KEY, SEESAW_BUTTON_SELECT, .keycode = BTN_SELECT },
  69. { KE_END, 0 }
  70. };
  71. static int seesaw_register_read(struct i2c_client *client, u16 reg, void *buf,
  72. int count)
  73. {
  74. __be16 register_buf = cpu_to_be16(reg);
  75. struct i2c_msg message_buf[2] = {
  76. {
  77. .addr = client->addr,
  78. .flags = client->flags,
  79. .len = sizeof(register_buf),
  80. .buf = (u8 *)&register_buf,
  81. },
  82. {
  83. .addr = client->addr,
  84. .flags = client->flags | I2C_M_RD,
  85. .len = count,
  86. .buf = (u8 *)buf,
  87. },
  88. };
  89. int ret;
  90. ret = i2c_transfer(client->adapter, message_buf,
  91. ARRAY_SIZE(message_buf));
  92. if (ret < 0)
  93. return ret;
  94. return 0;
  95. }
  96. static int seesaw_register_write_u8(struct i2c_client *client, u16 reg,
  97. u8 value)
  98. {
  99. u8 write_buf[sizeof(reg) + sizeof(value)];
  100. int ret;
  101. put_unaligned_be16(reg, write_buf);
  102. write_buf[sizeof(reg)] = value;
  103. ret = i2c_master_send(client, write_buf, sizeof(write_buf));
  104. if (ret < 0)
  105. return ret;
  106. return 0;
  107. }
  108. static int seesaw_register_write_u32(struct i2c_client *client, u16 reg,
  109. u32 value)
  110. {
  111. u8 write_buf[sizeof(reg) + sizeof(value)];
  112. int ret;
  113. put_unaligned_be16(reg, write_buf);
  114. put_unaligned_be32(value, write_buf + sizeof(reg));
  115. ret = i2c_master_send(client, write_buf, sizeof(write_buf));
  116. if (ret < 0)
  117. return ret;
  118. return 0;
  119. }
  120. static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data)
  121. {
  122. __be16 adc_data;
  123. __be32 read_buf;
  124. int err;
  125. err = seesaw_register_read(client, SEESAW_GPIO_BULK,
  126. &read_buf, sizeof(read_buf));
  127. if (err)
  128. return err;
  129. data->button_state = ~be32_to_cpu(read_buf);
  130. err = seesaw_register_read(client,
  131. SEESAW_ADC_BASE |
  132. (SEESAW_ADC_OFFSET + SEESAW_ANALOG_X),
  133. &adc_data, sizeof(adc_data));
  134. if (err)
  135. return err;
  136. /*
  137. * ADC reads left as max and right as 0, must be reversed since kernel
  138. * expects reports in opposite order.
  139. */
  140. data->x = SEESAW_JOYSTICK_MAX_AXIS - be16_to_cpu(adc_data);
  141. err = seesaw_register_read(client,
  142. SEESAW_ADC_BASE |
  143. (SEESAW_ADC_OFFSET + SEESAW_ANALOG_Y),
  144. &adc_data, sizeof(adc_data));
  145. if (err)
  146. return err;
  147. data->y = be16_to_cpu(adc_data);
  148. return 0;
  149. }
  150. static int seesaw_open(struct input_dev *input)
  151. {
  152. struct seesaw_gamepad *private = input_get_drvdata(input);
  153. private->button_state = 0;
  154. return 0;
  155. }
  156. static void seesaw_poll(struct input_dev *input)
  157. {
  158. struct seesaw_gamepad *private = input_get_drvdata(input);
  159. struct seesaw_data data;
  160. unsigned long changed;
  161. int err, i;
  162. err = seesaw_read_data(private->i2c_client, &data);
  163. if (err) {
  164. dev_err_ratelimited(&input->dev,
  165. "failed to read joystick state: %d\n", err);
  166. return;
  167. }
  168. input_report_abs(input, ABS_X, data.x);
  169. input_report_abs(input, ABS_Y, data.y);
  170. data.button_state &= SEESAW_BUTTON_MASK;
  171. changed = private->button_state ^ data.button_state;
  172. private->button_state = data.button_state;
  173. for_each_set_bit(i, &changed, fls(SEESAW_BUTTON_MASK)) {
  174. if (!sparse_keymap_report_event(input, i,
  175. data.button_state & BIT(i),
  176. false))
  177. dev_err_ratelimited(&input->dev,
  178. "failed to report keymap event");
  179. }
  180. input_sync(input);
  181. }
  182. static int seesaw_probe(struct i2c_client *client)
  183. {
  184. struct seesaw_gamepad *seesaw;
  185. u8 hardware_id;
  186. int err;
  187. err = seesaw_register_write_u8(client, SEESAW_STATUS_SWRST, 0xFF);
  188. if (err)
  189. return err;
  190. /* Wait for the registers to reset before proceeding */
  191. usleep_range(10000, 15000);
  192. seesaw = devm_kzalloc(&client->dev, sizeof(*seesaw), GFP_KERNEL);
  193. if (!seesaw)
  194. return -ENOMEM;
  195. err = seesaw_register_read(client, SEESAW_STATUS_HW_ID,
  196. &hardware_id, sizeof(hardware_id));
  197. if (err)
  198. return err;
  199. dev_dbg(&client->dev, "Adafruit Seesaw Gamepad, Hardware ID: %02x\n",
  200. hardware_id);
  201. /* Set Pin Mode to input and enable pull-up resistors */
  202. err = seesaw_register_write_u32(client, SEESAW_GPIO_DIRCLR_BULK,
  203. SEESAW_BUTTON_MASK);
  204. if (err)
  205. return err;
  206. err = seesaw_register_write_u32(client, SEESAW_GPIO_PULLENSET,
  207. SEESAW_BUTTON_MASK);
  208. if (err)
  209. return err;
  210. err = seesaw_register_write_u32(client, SEESAW_GPIO_BULK_SET,
  211. SEESAW_BUTTON_MASK);
  212. if (err)
  213. return err;
  214. seesaw->i2c_client = client;
  215. seesaw->input_dev = devm_input_allocate_device(&client->dev);
  216. if (!seesaw->input_dev)
  217. return -ENOMEM;
  218. seesaw->input_dev->id.bustype = BUS_I2C;
  219. seesaw->input_dev->name = "Adafruit Seesaw Gamepad";
  220. seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME;
  221. seesaw->input_dev->open = seesaw_open;
  222. input_set_drvdata(seesaw->input_dev, seesaw);
  223. input_set_abs_params(seesaw->input_dev, ABS_X,
  224. 0, SEESAW_JOYSTICK_MAX_AXIS,
  225. SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
  226. input_set_abs_params(seesaw->input_dev, ABS_Y,
  227. 0, SEESAW_JOYSTICK_MAX_AXIS,
  228. SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
  229. err = sparse_keymap_setup(seesaw->input_dev, seesaw_buttons_new, NULL);
  230. if (err) {
  231. dev_err(&client->dev,
  232. "failed to set up input device keymap: %d\n", err);
  233. return err;
  234. }
  235. err = input_setup_polling(seesaw->input_dev, seesaw_poll);
  236. if (err) {
  237. dev_err(&client->dev, "failed to set up polling: %d\n", err);
  238. return err;
  239. }
  240. input_set_poll_interval(seesaw->input_dev,
  241. SEESAW_GAMEPAD_POLL_INTERVAL_MS);
  242. input_set_max_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MAX);
  243. input_set_min_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MIN);
  244. err = input_register_device(seesaw->input_dev);
  245. if (err) {
  246. dev_err(&client->dev, "failed to register joystick: %d\n", err);
  247. return err;
  248. }
  249. return 0;
  250. }
  251. static const struct i2c_device_id seesaw_id_table[] = {
  252. { SEESAW_DEVICE_NAME },
  253. { /* Sentinel */ }
  254. };
  255. MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
  256. static const struct of_device_id seesaw_of_table[] = {
  257. { .compatible = "adafruit,seesaw-gamepad"},
  258. { /* Sentinel */ }
  259. };
  260. MODULE_DEVICE_TABLE(of, seesaw_of_table);
  261. static struct i2c_driver seesaw_driver = {
  262. .driver = {
  263. .name = SEESAW_DEVICE_NAME,
  264. .of_match_table = seesaw_of_table,
  265. },
  266. .id_table = seesaw_id_table,
  267. .probe = seesaw_probe,
  268. };
  269. module_i2c_driver(seesaw_driver);
  270. MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
  271. MODULE_DESCRIPTION("Adafruit Mini I2C Gamepad driver");
  272. MODULE_LICENSE("GPL");