in_gp2x.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include "../common/input.h"
  9. #include "in_gp2x.h"
  10. #define IN_GP2X_PREFIX "gp2x:"
  11. #define IN_GP2X_NBUTTONS 32
  12. /* note: in_gp2x hadles combos (if 2 btns have the same bind,
  13. * both must be pressed for action to happen) */
  14. static int in_gp2x_combo_keys = 0;
  15. static int in_gp2x_combo_acts = 0;
  16. static int gpiodev = -1; /* Wiz only */
  17. static int (*in_gp2x_get_bits)(void);
  18. static const char *in_gp2x_keys[IN_GP2X_NBUTTONS] = {
  19. [0 ... IN_GP2X_NBUTTONS-1] = NULL,
  20. [GP2X_BTN_UP] = "Up", [GP2X_BTN_LEFT] = "Left",
  21. [GP2X_BTN_DOWN] = "Down", [GP2X_BTN_RIGHT] = "Right",
  22. [GP2X_BTN_START] = "Start", [GP2X_BTN_SELECT] = "Select",
  23. [GP2X_BTN_L] = "L", [GP2X_BTN_R] = "R",
  24. [GP2X_BTN_A] = "A", [GP2X_BTN_B] = "B",
  25. [GP2X_BTN_X] = "X", [GP2X_BTN_Y] = "Y",
  26. [GP2X_BTN_VOL_DOWN] = "VOL DOWN",
  27. [GP2X_BTN_VOL_UP] = "VOL UP",
  28. [GP2X_BTN_PUSH] = "PUSH"
  29. };
  30. static int in_gp2x_get_mmsp2_bits(void)
  31. {
  32. extern volatile unsigned short *gp2x_memregs;
  33. int value;
  34. value = gp2x_memregs[0x1198>>1] & 0xff; // GPIO M
  35. if (value == 0xFD) value = 0xFA;
  36. if (value == 0xF7) value = 0xEB;
  37. if (value == 0xDF) value = 0xAF;
  38. if (value == 0x7F) value = 0xBE;
  39. value |= gp2x_memregs[0x1184>>1] & 0xFF00; // GPIO C
  40. value |= gp2x_memregs[0x1186>>1] << 16; // GPIO D
  41. value = ~value & 0x08c0ff55;
  42. return value;
  43. }
  44. static int in_gp2x_get_wiz_bits(void)
  45. {
  46. int r, value = 0;
  47. r = read(gpiodev, &value, 4);
  48. if (value & 0x02)
  49. value |= 0x05;
  50. if (value & 0x08)
  51. value |= 0x14;
  52. if (value & 0x20)
  53. value |= 0x50;
  54. if (value & 0x80)
  55. value |= 0x41;
  56. /* convert to GP2X style */
  57. value &= 0x7ff55;
  58. if (value & (1 << 16))
  59. value |= 1 << GP2X_BTN_VOL_UP;
  60. if (value & (1 << 17))
  61. value |= 1 << GP2X_BTN_VOL_DOWN;
  62. if (value & (1 << 18))
  63. value |= 1 << GP2X_BTN_PUSH;
  64. value &= ~0x70000;
  65. return value;
  66. }
  67. #ifdef FAKE_IN_GP2X
  68. volatile unsigned short *gp2x_memregs;
  69. int gp2x_dev_id = -1;
  70. static int in_gp2x_get_fake_bits(void)
  71. {
  72. extern int current_keys;
  73. return current_keys;
  74. }
  75. #endif
  76. static void in_gp2x_probe(void)
  77. {
  78. switch (gp2x_dev_id)
  79. {
  80. case GP2X_DEV_GP2X:
  81. in_gp2x_get_bits = in_gp2x_get_mmsp2_bits;
  82. break;
  83. case GP2X_DEV_WIZ:
  84. gpiodev = open("/dev/GPIO", O_RDONLY);
  85. if (gpiodev < 0) {
  86. perror("in_gp2x: couldn't open /dev/GPIO");
  87. return;
  88. }
  89. in_gp2x_get_bits = in_gp2x_get_wiz_bits;
  90. break;
  91. // we'll use evdev for Caanoo
  92. default:
  93. #ifdef FAKE_IN_GP2X
  94. in_gp2x_get_bits = in_gp2x_get_fake_bits;
  95. break;
  96. #endif
  97. return;
  98. }
  99. in_register(IN_GP2X_PREFIX "GP2X pad", -1, NULL,
  100. IN_GP2X_NBUTTONS, in_gp2x_keys, 1);
  101. }
  102. static void in_gp2x_free(void *drv_data)
  103. {
  104. if (gpiodev >= 0) {
  105. close(gpiodev);
  106. gpiodev = -1;
  107. }
  108. }
  109. static const char * const *
  110. in_gp2x_get_key_names(int *count)
  111. {
  112. *count = IN_GP2X_NBUTTONS;
  113. return in_gp2x_keys;
  114. }
  115. /* ORs result with pressed buttons */
  116. static int in_gp2x_update(void *drv_data, const int *binds, int *result)
  117. {
  118. int type_start = 0;
  119. int i, t, keys;
  120. keys = in_gp2x_get_bits();
  121. if (keys & in_gp2x_combo_keys) {
  122. result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, GP2X_BTN_PUSH,
  123. in_gp2x_combo_keys, in_gp2x_combo_acts);
  124. type_start = IN_BINDTYPE_PLAYER12;
  125. }
  126. for (i = 0; keys; i++, keys >>= 1) {
  127. if (!(keys & 1))
  128. continue;
  129. for (t = type_start; t < IN_BINDTYPE_COUNT; t++)
  130. result[t] |= binds[IN_BIND_OFFS(i, t)];
  131. }
  132. return 0;
  133. }
  134. int in_gp2x_update_keycode(void *data, int *is_down)
  135. {
  136. static int old_val = 0;
  137. int val, diff, i;
  138. val = in_gp2x_get_bits();
  139. diff = val ^ old_val;
  140. if (diff == 0)
  141. return -1;
  142. /* take one bit only */
  143. for (i = 0; i < sizeof(diff)*8; i++)
  144. if (diff & (1<<i))
  145. break;
  146. old_val ^= 1 << i;
  147. if (is_down)
  148. *is_down = !!(val & (1<<i));
  149. return i;
  150. }
  151. static const struct {
  152. short key;
  153. short pbtn;
  154. } key_pbtn_map[] =
  155. {
  156. { GP2X_BTN_UP, PBTN_UP },
  157. { GP2X_BTN_DOWN, PBTN_DOWN },
  158. { GP2X_BTN_LEFT, PBTN_LEFT },
  159. { GP2X_BTN_RIGHT, PBTN_RIGHT },
  160. { GP2X_BTN_B, PBTN_MOK },
  161. { GP2X_BTN_X, PBTN_MBACK },
  162. { GP2X_BTN_A, PBTN_MA2 },
  163. { GP2X_BTN_Y, PBTN_MA3 },
  164. { GP2X_BTN_L, PBTN_L },
  165. { GP2X_BTN_R, PBTN_R },
  166. { GP2X_BTN_SELECT, PBTN_MENU },
  167. };
  168. #define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
  169. static int in_gp2x_menu_translate(void *drv_data, int keycode)
  170. {
  171. int i;
  172. if (keycode < 0)
  173. {
  174. /* menu -> kc */
  175. keycode = -keycode;
  176. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  177. if (key_pbtn_map[i].pbtn == keycode)
  178. return key_pbtn_map[i].key;
  179. }
  180. else
  181. {
  182. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  183. if (key_pbtn_map[i].key == keycode)
  184. return key_pbtn_map[i].pbtn;
  185. }
  186. return 0;
  187. }
  188. #if 0 // TODO: move to pico
  189. static const struct {
  190. short code;
  191. char btype;
  192. char bit;
  193. } in_gp2x_defbinds[] =
  194. {
  195. /* MXYZ SACB RLDU */
  196. { BTN_UP, IN_BINDTYPE_PLAYER12, 0 },
  197. { BTN_DOWN, IN_BINDTYPE_PLAYER12, 1 },
  198. { BTN_LEFT, IN_BINDTYPE_PLAYER12, 2 },
  199. { BTN_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
  200. { BTN_X, IN_BINDTYPE_PLAYER12, 4 }, /* B */
  201. { BTN_B, IN_BINDTYPE_PLAYER12, 5 }, /* C */
  202. { BTN_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
  203. { BTN_START, IN_BINDTYPE_PLAYER12, 7 },
  204. { BTN_SELECT, IN_BINDTYPE_EMU, PEVB_MENU },
  205. // { BTN_Y, IN_BINDTYPE_EMU, PEVB_SWITCH_RND },
  206. { BTN_L, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
  207. { BTN_R, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
  208. { BTN_VOL_UP, IN_BINDTYPE_EMU, PEVB_VOL_UP },
  209. { BTN_VOL_DOWN, IN_BINDTYPE_EMU, PEVB_VOL_DOWN },
  210. { 0, 0, 0 },
  211. };
  212. #endif
  213. /* remove binds of missing keys, count remaining ones */
  214. static int in_gp2x_clean_binds(void *drv_data, int *binds, int *def_binds)
  215. {
  216. int i, count = 0;
  217. // int eb, have_vol = 0, have_menu = 0;
  218. for (i = 0; i < IN_GP2X_NBUTTONS; i++) {
  219. int t, offs;
  220. for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
  221. offs = IN_BIND_OFFS(i, t);
  222. if (in_gp2x_keys[i] == NULL)
  223. binds[offs] = def_binds[offs] = 0;
  224. if (binds[offs])
  225. count++;
  226. }
  227. #if 0
  228. eb = binds[IN_BIND_OFFS(i, IN_BINDTYPE_EMU)];
  229. if (eb & (PEV_VOL_DOWN|PEV_VOL_UP))
  230. have_vol = 1;
  231. if (eb & PEV_MENU)
  232. have_menu = 1;
  233. #endif
  234. }
  235. // TODO: move to pico
  236. #if 0
  237. /* autobind some important keys, if they are unbound */
  238. if (!have_vol && binds[GP2X_BTN_VOL_UP] == 0 && binds[GP2X_BTN_VOL_DOWN] == 0) {
  239. binds[IN_BIND_OFFS(GP2X_BTN_VOL_UP, IN_BINDTYPE_EMU)] = PEV_VOL_UP;
  240. binds[IN_BIND_OFFS(GP2X_BTN_VOL_DOWN, IN_BINDTYPE_EMU)] = PEV_VOL_DOWN;
  241. count += 2;
  242. }
  243. if (!have_menu) {
  244. binds[IN_BIND_OFFS(GP2X_BTN_SELECT, IN_BINDTYPE_EMU)] = PEV_MENU;
  245. count++;
  246. }
  247. #endif
  248. in_combos_find(binds, GP2X_BTN_PUSH, &in_gp2x_combo_keys, &in_gp2x_combo_acts);
  249. return count;
  250. }
  251. static const in_drv_t in_gp2x_drv = {
  252. .prefix = IN_GP2X_PREFIX,
  253. .probe = in_gp2x_probe,
  254. .free = in_gp2x_free,
  255. .get_key_names = in_gp2x_get_key_names,
  256. .clean_binds = in_gp2x_clean_binds,
  257. .update = in_gp2x_update,
  258. .update_keycode = in_gp2x_update_keycode,
  259. .menu_translate = in_gp2x_menu_translate,
  260. };
  261. void in_gp2x_init(const struct in_default_bind *defbinds)
  262. {
  263. if (gp2x_dev_id == GP2X_DEV_WIZ)
  264. in_gp2x_keys[GP2X_BTN_START] = "MENU";
  265. in_gp2x_combo_keys = in_gp2x_combo_acts = 0;
  266. in_register_driver(&in_gp2x_drv, defbinds);
  267. }