gpio_mapping.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <assert.h>
  10. #include <sys/select.h>
  11. #include <sys/time.h>
  12. #include <linux/input.h>
  13. #include "gpio_mapping.h"
  14. #include "driver_pcal6416a.h"
  15. #include "driver_axp209.h"
  16. /****************************************************************
  17. * Defines
  18. ****************************************************************/
  19. #define die(str, args...) do { \
  20. perror(str); \
  21. return(EXIT_FAILURE); \
  22. } while(0)
  23. #define DEBUG_GPIO_PRINTF (0)
  24. #define ERROR_GPIO_PRINTF (1)
  25. #if (DEBUG_GPIO_PRINTF)
  26. #define GPIO_PRINTF(...) printf(__VA_ARGS__);
  27. #else
  28. #define GPIO_PRINTF(...)
  29. #endif
  30. #if (ERROR_GPIO_PRINTF)
  31. #define GPIO_ERROR_PRINTF(...) printf(__VA_ARGS__);
  32. #else
  33. #define GPIO_ERROR_PRINTF(...)
  34. #endif
  35. // This define forces to perform a gpio sanity check after a timeout.
  36. // If not declared, there will be no timeout and no periodical sanity check of GPIO expander values
  37. //#define TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP 1
  38. #define TIMEOUT_MICROSEC_SANITY_CHECK_GPIO_EXP (30*1000)
  39. // Comment this for debug purposes on cards or eval boards that do not have the AXP209
  40. #define ENABLE_AXP209_INTERRUPTS
  41. #define KEY_IDX_MAPPED_FOR_SHORT_PEK_PRESS 16 //KEY_Q
  42. #define KEY_IDX_MAPPED_FOR_LONG_PEK_PRESS 28 //KEY_ENTER
  43. /****************************************************************
  44. * Static variables
  45. ****************************************************************/
  46. static int nb_mapped_gpios;
  47. static int * gpio_pins;
  48. STRUCT_MAPPED_GPIO * chained_list_mapping;
  49. static int max_fd = 0;
  50. static int gpio_fd_interrupt_expander_gpio;
  51. static int gpio_fd_interrupt_axp209;
  52. static fd_set fds;
  53. static bool * mask_gpio_value;
  54. static bool interrupt_i2c_expander_found = false;
  55. static bool interrupt_axp209_found = false;
  56. static bool mapping_PEK_short_press_activated = false;
  57. static bool mapping_PEK_long_press_activated = false;
  58. /****************************************************************
  59. * Static functions
  60. ****************************************************************/
  61. /***** Add a fd to fd_set, and update max_fd_nb ******/
  62. static int safe_fd_set(int fd, fd_set* list_fds, int* max_fd_nb) {
  63. assert(max_fd_nb != NULL);
  64. FD_SET(fd, list_fds);
  65. if (fd > *max_fd_nb) {
  66. *max_fd_nb = fd;
  67. }
  68. return 0;
  69. }
  70. /***** Clear fd from fds, update max fd if needed *****/
  71. static int safe_fd_clr(int fd, fd_set* list_fds, int* max_fd_nb) {
  72. assert(max_fd_nb != NULL);
  73. FD_CLR(fd, list_fds);
  74. if (fd == *max_fd_nb) {
  75. (*max_fd_nb)--;
  76. }
  77. return 0;
  78. }
  79. /***** Apply mapping activation fuction *****/
  80. static void apply_mapping_activation(STRUCT_MAPPED_GPIO * node_mapping){
  81. node_mapping->activated = true;
  82. if(node_mapping->type_mapping == TYPE_MAPPING_KEYBOARD){
  83. GPIO_PRINTF("Apply mapping activation fct: Key event: %d\n", node_mapping->key_value);
  84. sendKey(node_mapping->key_value, 1);
  85. //sendKeyAndStopKey(node_mapping->key_value);
  86. }
  87. else if(node_mapping->type_mapping == TYPE_MAPPING_SHELL_COMMAND){
  88. GPIO_PRINTF("Apply mapping activation fct: shell command \"%s\"\n", node_mapping->shell_command);
  89. system(node_mapping->shell_command);
  90. }
  91. }
  92. /***** Apply mapping desactivation function *****/
  93. static void apply_mapping_desactivation(STRUCT_MAPPED_GPIO * node_mapping){
  94. node_mapping->activated = false;
  95. if(node_mapping->type_mapping == TYPE_MAPPING_KEYBOARD){
  96. GPIO_PRINTF("Apply mapping desactivation fct: Key event: %d\n", node_mapping->key_value);
  97. sendKey(node_mapping->key_value, 0);
  98. }
  99. else if(node_mapping->type_mapping == TYPE_MAPPING_SHELL_COMMAND){
  100. //GPIO_PRINTF("Apply mapping desactivation fct: shell command \"%s\"\n", node_mapping->shell_command);
  101. }
  102. }
  103. static void find_and_call_mapping_function(int idx_gpio_interrupted,
  104. STRUCT_MAPPED_GPIO * cl_mapping,
  105. bool* mask_gpio_current_interrupts,
  106. bool * mask_gpio_values,
  107. bool activation){
  108. // Init variables
  109. STRUCT_MAPPED_GPIO * current = cl_mapping;
  110. bool mapping_found = false;
  111. // Search if there are mappings to deactivate
  112. while (current != NULL) {
  113. int i;
  114. bool gpio_found_pin_in_mapping = false;
  115. bool all_gpio_activated_in_mapping = true;
  116. //GPIO_PRINTF(" Mapping searching for idx_gpio_interrupted: %d, and %s: \n", idx_gpio_interrupted, activation?"activation":"deactivation")
  117. for (i=0; i < current->nb_simultaneous_pins; i++){
  118. //GPIO_PRINTF(" Pin in mapping: %d, pin_idx=%d\n", gpio_pins[current->pins_idx[i]], current->pins_idx[i]);
  119. // Find if current mapping contains interrupted pin
  120. if (current->pins_idx[i] == idx_gpio_interrupted){
  121. gpio_found_pin_in_mapping = true;
  122. }
  123. // Check if all other pins of current mapping were already activated in previous mask
  124. if(!mask_gpio_values[current->pins_idx[i]]){
  125. all_gpio_activated_in_mapping = false;
  126. }
  127. }
  128. // If this mapping contains the interrupted pin and all other pins activated:
  129. if(gpio_found_pin_in_mapping && all_gpio_activated_in_mapping){
  130. // Treating activation cases
  131. if(activation){
  132. // if real mapping already found => need to deactivate previously activated ones
  133. if(mapping_found && current->activated){
  134. GPIO_PRINTF(" Mapping Deactivation because real one already found: GPIO %d found in following activated mapping: \n",
  135. gpio_pins[idx_gpio_interrupted]);
  136. print_chained_list_node(current);
  137. apply_mapping_desactivation(current);
  138. }
  139. else if(!mapping_found){ // If this is the real mapping
  140. if(current->activated){
  141. GPIO_ERROR_PRINTF("WARNING in find_and_call_mapping_function - Activating already activated mapping %s\n",
  142. current->fct_help_str);
  143. }
  144. // Print information and activate mapping
  145. GPIO_PRINTF(" Mapping Activation: GPIO %d found in following deactivated mapping: \n",
  146. gpio_pins[idx_gpio_interrupted]);
  147. print_chained_list_node(current);
  148. apply_mapping_activation(current);
  149. }
  150. }
  151. else{ // Treating deactivation cases
  152. if(current->activated){
  153. GPIO_PRINTF(" Mapping Desactivation: GPIO %d found in following activated mapping: \n",
  154. gpio_pins[idx_gpio_interrupted]);
  155. print_chained_list_node(current);
  156. apply_mapping_desactivation(current);
  157. }
  158. }
  159. // Set that mapping has been found
  160. mapping_found = true;
  161. }
  162. // Next node in chained list
  163. current = current->next_mapped_gpio;
  164. }
  165. }
  166. /***** Init GPIO Interrupt i2c expander fd *****/
  167. static int init_gpio_interrupt(int pin_nb, int *fd_saved, const char *edge)
  168. {
  169. // Variables
  170. GPIO_PRINTF("Initializing Interrupt on GPIO pin: %d\n", pin_nb);
  171. //Initializing I2C interrupt GPIO
  172. gpio_export(pin_nb);
  173. gpio_set_edge(pin_nb, edge); // Can be rising, falling or both
  174. //gpio_set_edge(pin_nb, "both"); // Can be rising, falling or both
  175. //gpio_set_edge(pin_nb, "falling"); // Can be rising, falling or both
  176. *fd_saved = gpio_fd_open(pin_nb, O_RDONLY);
  177. GPIO_PRINTF("fd is: %d\n", *fd_saved);
  178. // add stdin and the sock fd to fds fd_set
  179. safe_fd_set(*fd_saved, &fds, &max_fd);
  180. return 0;
  181. }
  182. /***** DeInit GPIO Interrupt i2c expander fd *****/
  183. static int deinit_gpio_interrupt(int fd_saved)
  184. {
  185. GPIO_PRINTF("DeInitializing Interrupt on GPIO pin fd: %d\n", fd_saved);
  186. // Remove stdin and sock fd from fds fd_set
  187. safe_fd_clr(fd_saved, &fds, &max_fd);
  188. // Unexport GPIO
  189. gpio_fd_close(fd_saved);
  190. return 0;
  191. }
  192. /****************************************************************
  193. * Public functions
  194. ****************************************************************/
  195. /***** Init I2C expander pin mappings *****/
  196. int init_mapping_gpios(int * gpio_pins_to_declare, int nb_gpios_to_declare,
  197. STRUCT_MAPPED_GPIO * chained_list_mapping_gpios)
  198. {
  199. // Variables
  200. int idx_gpio;
  201. unsigned int cur_pin_nb;
  202. // Store arguments
  203. nb_mapped_gpios = nb_gpios_to_declare;
  204. gpio_pins = gpio_pins_to_declare;
  205. chained_list_mapping = chained_list_mapping_gpios;
  206. // Init values
  207. mask_gpio_value = malloc(nb_mapped_gpios*sizeof(bool));
  208. memset(mask_gpio_value, false, nb_mapped_gpios*sizeof(bool));
  209. STRUCT_MAPPED_GPIO * current = chained_list_mapping;
  210. do{
  211. //set mapping deactivated
  212. current->activated = false;
  213. // Next node in chained list
  214. current = current->next_mapped_gpio;
  215. } while(current != NULL);
  216. // Init fds fd_set
  217. FD_ZERO(&fds);
  218. // Init GPIO interrupt from I2C GPIO expander
  219. GPIO_PRINTF(" Initiating interrupt for GPIO_PIN_I2C_EXPANDER_INTERRUPT\n");
  220. init_gpio_interrupt(GPIO_PIN_I2C_EXPANDER_INTERRUPT, &gpio_fd_interrupt_expander_gpio, "both"); // Can be rising, falling or both
  221. // Init I2C expander
  222. pcal6416a_init();
  223. #ifdef ENABLE_AXP209_INTERRUPTS
  224. // Init GPIO interrupt from AXP209
  225. GPIO_PRINTF(" Initiating interrupt for GPIO_PIN_AXP209_INTERRUPT\n");
  226. init_gpio_interrupt(GPIO_PIN_AXP209_INTERRUPT, &gpio_fd_interrupt_axp209, "falling");
  227. // Init AXP209
  228. axp209_init();
  229. #endif //ENABLE_AXP209_INTERRUPTS
  230. return 0;
  231. }
  232. /***** DeInit GPIO fds *****/
  233. int deinit_mapping_gpios(void)
  234. {
  235. // DeInit GPIO interrupt from I2C expander
  236. GPIO_PRINTF(" DeInitiating interrupt for GPIO_PIN_I2C_EXPANDER_INTERRUPT\n");
  237. deinit_gpio_interrupt(gpio_fd_interrupt_expander_gpio);
  238. // DeInit I2C expander
  239. pcal6416a_deinit();
  240. #ifdef ENABLE_AXP209_INTERRUPTS
  241. // DeInit GPIO interrupt from AXP209
  242. GPIO_PRINTF(" DeInitiating interrupt for GPIO_PIN_AXP209_INTERRUPT\n");
  243. deinit_gpio_interrupt(gpio_fd_interrupt_axp209);
  244. // DeInit AXP209
  245. axp209_deinit();
  246. #endif //ENABLE_AXP209_INTERRUPTS
  247. return 0;
  248. }
  249. /***** Listen GPIOs interrupts *****/
  250. int listen_gpios_interrupts(void)
  251. {
  252. // Variables
  253. char buffer[2];
  254. int value;
  255. int idx_gpio;
  256. int nb_interrupts = 0;
  257. bool previous_mask_gpio_value[nb_mapped_gpios];
  258. bool mask_gpio_current_interrupts[nb_mapped_gpios];
  259. // Back up master
  260. fd_set dup = fds;
  261. // Init masks
  262. memcpy(previous_mask_gpio_value, mask_gpio_value, nb_mapped_gpios*sizeof(bool));
  263. memset(mask_gpio_value, false, nb_mapped_gpios*sizeof(bool));
  264. memset(mask_gpio_current_interrupts, false, nb_mapped_gpios*sizeof(bool));
  265. // If interrupt not already found, waiting for interrupt or timeout, Note the max_fd+1
  266. if(!interrupt_i2c_expander_found && !interrupt_axp209_found){
  267. // Listen to interrupts
  268. #ifdef TIMEOUT_MICROSEC_SANITY_CHECK_GPIO_EXP
  269. struct timeval timeout = {0, TIMEOUT_MICROSEC_SANITY_CHECK_GPIO_EXP};
  270. nb_interrupts = select(max_fd+1, NULL, NULL, &dup, &timeout);
  271. #elif TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP
  272. struct timeval timeout = {TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP, 0};
  273. nb_interrupts = select(max_fd+1, NULL, NULL, &dup, &timeout);
  274. #else
  275. nb_interrupts = select(max_fd+1, NULL, NULL, &dup, NULL);
  276. #endif //TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP
  277. if(!nb_interrupts){
  278. // Timeout case
  279. GPIO_PRINTF(" Timeout, forcing sanity check\n");
  280. // Timeout forcing a "Found interrupt" event for sanity check
  281. interrupt_i2c_expander_found = true;
  282. interrupt_axp209_found = true;
  283. }
  284. else if ( nb_interrupts < 0) {
  285. perror("select");
  286. return -1;
  287. }
  288. }
  289. if(nb_interrupts){
  290. // Check if interrupt from I2C expander or AXP209
  291. // Check which cur_fd is available for read
  292. for (int cur_fd = 0; cur_fd <= max_fd; cur_fd++) {
  293. if (FD_ISSET(cur_fd, &dup)) {
  294. // Rewind file
  295. lseek(cur_fd, 0, SEEK_SET);
  296. // Read current gpio value
  297. if (read(cur_fd, & buffer, 2) != 2) {
  298. perror("read");
  299. break;
  300. }
  301. // remove end of line char
  302. buffer[1] = '\0';
  303. value = atoi(buffer);
  304. //value = 1-atoi(buffer);
  305. // Found interrupt
  306. if(cur_fd == gpio_fd_interrupt_expander_gpio){
  307. GPIO_PRINTF("Found interrupt generated by PCAL6416AHF \r\n");
  308. interrupt_i2c_expander_found = true;
  309. }
  310. else if(cur_fd == gpio_fd_interrupt_axp209){
  311. GPIO_PRINTF("Found interrupt generated by AXP209\r\n");
  312. interrupt_axp209_found = true;
  313. }
  314. }
  315. }
  316. }
  317. #ifdef ENABLE_AXP209_INTERRUPTS
  318. if(interrupt_axp209_found){
  319. GPIO_PRINTF(" Processing interrupt AXP209\n");
  320. int val_int_bank_3 = axp209_read_interrupt_bank_3();
  321. if(val_int_bank_3 < 0){
  322. GPIO_PRINTF(" Could not read AXP209 with I2C\n");
  323. return 0;
  324. }
  325. interrupt_axp209_found = false;
  326. if(val_int_bank_3 & AXP209_INTERRUPT_PEK_SHORT_PRESS){
  327. GPIO_PRINTF(" AXP209 short PEK key press detected\n");
  328. sendKeyAndStopKey(KEY_IDX_MAPPED_FOR_SHORT_PEK_PRESS);
  329. /*sendKey(KEY_IDX_MAPPED_FOR_SHORT_PEK_PRESS, !mapping_PEK_short_press_activated);
  330. mapping_PEK_short_press_activated = !mapping_PEK_short_press_activated;*/
  331. }
  332. if(val_int_bank_3 & AXP209_INTERRUPT_PEK_LONG_PRESS){
  333. GPIO_PRINTF(" AXP209 long PEK key press detected\n");
  334. sendKeyAndStopKey(KEY_IDX_MAPPED_FOR_LONG_PEK_PRESS);
  335. /*sendKey(KEY_IDX_MAPPED_FOR_LONG_PEK_PRESS, !mapping_PEK_long_press_activated);
  336. mapping_PEK_long_press_activated = !mapping_PEK_long_press_activated;*/
  337. }
  338. }
  339. #endif //ENABLE_AXP209_INTERRUPTS
  340. if(interrupt_i2c_expander_found){
  341. GPIO_PRINTF(" Processing interrupt PCAL6416AHF\n");
  342. // Read I2C GPIO masks:
  343. int val_i2c_mask_interrupted = pcal6416a_read_mask_interrupts();
  344. if(val_i2c_mask_interrupted < 0){
  345. GPIO_PRINTF(" Could not read pcal6416a_read_mask_interrupts\n");
  346. return 0;
  347. }
  348. int val_i2c_mask_active = pcal6416a_read_mask_active_GPIOs();
  349. if(val_i2c_mask_active < 0){
  350. GPIO_PRINTF(" Could not read pcal6416a_read_mask_active_GPIOs\n");
  351. return 0;
  352. }
  353. interrupt_i2c_expander_found = false;
  354. // Find GPIO idx correspondance
  355. for (idx_gpio=0; idx_gpio<nb_mapped_gpios; idx_gpio++){
  356. uint16_t tmp_mask_gpio = (1 << gpio_pins[idx_gpio]);
  357. // Found GPIO idx in active GPIOs
  358. if(val_i2c_mask_active & tmp_mask_gpio){
  359. mask_gpio_value[idx_gpio] = true;
  360. }
  361. // Found GPIO idx in interrupt mask
  362. if(val_i2c_mask_interrupted & tmp_mask_gpio){
  363. // Print information
  364. GPIO_PRINTF(" --> Interrupt GPIO: %d, idx_pin: %d\n", gpio_pins[idx_gpio], idx_gpio);
  365. mask_gpio_current_interrupts[idx_gpio] = true;
  366. }
  367. // Sanity check: if we missed an interrupt for some reason, check if the new values are the same
  368. if( !mask_gpio_current_interrupts[idx_gpio] &&
  369. (mask_gpio_value[idx_gpio] != previous_mask_gpio_value[idx_gpio]) ){
  370. // Print information
  371. GPIO_PRINTF(" --> No Interrupt (missed) but value has changed on GPIO: %d, idx_pin: %d\n", gpio_pins[idx_gpio], idx_gpio);
  372. mask_gpio_current_interrupts[idx_gpio] = true;
  373. }
  374. }
  375. // Find and call mapping functions (after all active gpios have been assigned):
  376. for (idx_gpio=0; idx_gpio<nb_mapped_gpios; idx_gpio++){
  377. if(!mask_gpio_current_interrupts[idx_gpio]) continue;
  378. if (mask_gpio_value[idx_gpio]){
  379. find_and_call_mapping_function(idx_gpio,
  380. chained_list_mapping,
  381. mask_gpio_current_interrupts,
  382. mask_gpio_value,
  383. true);
  384. }
  385. else{
  386. find_and_call_mapping_function(idx_gpio,
  387. chained_list_mapping,
  388. mask_gpio_current_interrupts,
  389. previous_mask_gpio_value,
  390. false);
  391. }
  392. }
  393. }
  394. return 0;
  395. }