gpio_mapping.c 14 KB

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