read_conf_file.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <errno.h>
  8. #include <sys/select.h>
  9. #include <linux/input.h>
  10. #include "read_conf_file.h"
  11. #include <assert.h>
  12. /****************************************************************
  13. * Defines
  14. ****************************************************************/
  15. #define die(str, args...) do { \
  16. perror(str); \
  17. return(EXIT_FAILURE); \
  18. } while(0)
  19. #define DEBUG_READ_CONF_FILE_PRINTF (0)
  20. #if (DEBUG_READ_CONF_FILE_PRINTF)
  21. #define READ_CONF_FILE_PRINTF(...) printf(__VA_ARGS__);
  22. #else
  23. #define READ_CONF_FILE_PRINTF(...)
  24. #endif
  25. /****************************************************************
  26. * Extern variables
  27. ****************************************************************/
  28. extern key_names_s key_names[];
  29. /****************************************************************
  30. * Static variables
  31. ****************************************************************/
  32. static STRUCT_MAPPED_GPIO * head_chained_list_mapping_gpio = NULL;
  33. static int count_valid_gpios = 0;
  34. static int gpio_pins[MAX_NUM_GPIO];
  35. /****************************************************************
  36. * Static functions
  37. ****************************************************************/
  38. /* Return linux Key code from corresponding str*/
  39. static int find_key(const char *name)
  40. {
  41. int i=0;
  42. while(key_names[i].code >= 0){
  43. if(!strncmp(key_names[i].name, name, 32))break;
  44. i++;
  45. }
  46. if(key_names[i].code < 0){
  47. i = 0;
  48. }
  49. return i;
  50. }
  51. /* Return pin idx in the array of instanciated pins */
  52. static int get_idx_pin(int* ptr_list_gpio_pins, int size_list_gpio_pins, int pin_number_to_find){
  53. int idx;
  54. for (idx=0; idx<size_list_gpio_pins; idx++){
  55. if(ptr_list_gpio_pins[idx] == pin_number_to_find){
  56. return idx;
  57. }
  58. }
  59. // if we get here, then we did not find the pin:
  60. idx=-1;
  61. return idx;
  62. }
  63. /* function to swap data of two nodes a and b in chained list */
  64. static void swap(STRUCT_MAPPED_GPIO *a, STRUCT_MAPPED_GPIO *b)
  65. {
  66. STRUCT_MAPPED_GPIO temp;
  67. memcpy(&temp, a, sizeof(STRUCT_MAPPED_GPIO));
  68. memcpy(a, b, sizeof(STRUCT_MAPPED_GPIO));
  69. memcpy(b, &temp, sizeof(STRUCT_MAPPED_GPIO));
  70. b->next_mapped_gpio = a->next_mapped_gpio;
  71. a->next_mapped_gpio = b;
  72. }
  73. /* Bubble sort the given linked list */
  74. static void bubbleSort(STRUCT_MAPPED_GPIO *head)
  75. {
  76. int swapped, i;
  77. STRUCT_MAPPED_GPIO *ptr1 = head;
  78. STRUCT_MAPPED_GPIO *lptr = NULL;
  79. /* Checking for empty list */
  80. if (ptr1 == NULL)
  81. return;
  82. do
  83. {
  84. swapped = 0;
  85. ptr1 = head;
  86. while (ptr1->next_mapped_gpio != lptr)
  87. {
  88. if (ptr1->nb_simultaneous_pins < ptr1->next_mapped_gpio->nb_simultaneous_pins)
  89. {
  90. swap(ptr1, ptr1->next_mapped_gpio);
  91. swapped = 1;
  92. }
  93. ptr1 = ptr1->next_mapped_gpio;
  94. }
  95. lptr = ptr1;
  96. }
  97. while (swapped);
  98. }
  99. /* Push new node in chained list */
  100. static void push(STRUCT_MAPPED_GPIO ** head, STRUCT_MAPPED_GPIO * new_mapping) {
  101. STRUCT_MAPPED_GPIO ** current = head;
  102. while (*current != NULL) {
  103. current = &(*current)->next_mapped_gpio;
  104. }
  105. /* now we can add a new variable */
  106. *current = malloc(sizeof(STRUCT_MAPPED_GPIO));
  107. memcpy(*current, new_mapping, sizeof(STRUCT_MAPPED_GPIO));
  108. (*current)->next_mapped_gpio = NULL;
  109. }
  110. /****************************************************************
  111. * Public functions
  112. ****************************************************************/
  113. void get_mapping_from_conf_file(STRUCT_MAPPED_GPIO ** chained_list_mapping,
  114. int* nb_valid_gpios, int ** valid_gpio_pins){
  115. /* Variables */
  116. READ_CONF_FILE_PRINTF("Reading the config file:\n");
  117. FILE *fp;
  118. char ln[MAX_LN_LENGTH];
  119. int lnno = 0;
  120. char conffile[80];
  121. bool pins_declaration_line = true;
  122. /* search for the conf file in ~/.funkey_gpio_mapping.conf and /etc/funkey_gpio_mapping.conf */
  123. sprintf(conffile, "%s/.funkey_gpio_mapping.conf", getenv("HOME"));
  124. fp = fopen(conffile, "r");
  125. if(!fp){
  126. fp = fopen("/etc/funkey_gpio_mapping.conf", "r");
  127. if(!fp){
  128. fp = fopen("./funkey_gpio_mapping.conf", "r");
  129. if(!fp){
  130. perror(conffile);
  131. perror("/etc/funkey_gpio_mapping.conf");
  132. perror("./funkey_gpio_mapping.conf");
  133. }
  134. sprintf(conffile, "./funkey_gpio_mapping.conf");
  135. }
  136. else{
  137. sprintf(conffile, "/etc/funkey_gpio_mapping.conf");
  138. }
  139. }
  140. if(fp){
  141. READ_CONF_FILE_PRINTF("Config file found at %s\n", conffile);
  142. }
  143. /* Main loop to read conf file (purposely exploded and not in multiple sub-functions) */
  144. while(fp && !feof(fp)){
  145. if(fgets(ln, MAX_LN_LENGTH, fp)){
  146. lnno++;
  147. if(strlen(ln) > 1){
  148. if(ln[0]=='#')continue;
  149. READ_CONF_FILE_PRINTF("\nCurrent line : %s\n", ln);
  150. // ************ Pins declaration ************
  151. if(pins_declaration_line){
  152. char* token;
  153. int token_int;
  154. //count nb valid GPIOs and store them
  155. token = strtok(ln, ",");
  156. while(token != NULL){
  157. token_int = atoi(token);
  158. if(token_int || !strcmp(token, "0")){
  159. gpio_pins[count_valid_gpios] = token_int;
  160. count_valid_gpios++;
  161. READ_CONF_FILE_PRINTF("GPIO %d declared\n", token_int);
  162. }
  163. else{
  164. READ_CONF_FILE_PRINTF("Could not declare GPIO: %s\n", token);
  165. }
  166. token = strtok(NULL, ",");
  167. }
  168. pins_declaration_line = false;
  169. }
  170. // ************ Pins mapping ************
  171. else{
  172. STRUCT_MAPPED_GPIO cur_gpio_mapping;
  173. char* end_ln;
  174. char* token_comma;
  175. char * current_arg;
  176. int cur_arg_idx = MAPPING_ARG_PINS;
  177. int idx_pin = 0;
  178. int cur_pin;
  179. bool add_current_mapping = true;
  180. token_comma = strtok_r(ln, ",", &end_ln);
  181. while(token_comma != NULL && cur_arg_idx < NB_MAPPING_ARG_NAMES && add_current_mapping){
  182. current_arg= token_comma;
  183. //remove_initial_spaces:
  184. while(*current_arg==' ' && *current_arg!=0){current_arg++;}
  185. READ_CONF_FILE_PRINTF(" Current arg: %s\n", current_arg);
  186. //Handle current mapping arg
  187. switch(cur_arg_idx){
  188. case MAPPING_ARG_PINS:
  189. //count nb valid GPIOs and store them
  190. ;char* end_arg;
  191. char * token_plus = strtok_r(current_arg, "+", &end_arg);
  192. while(token_plus != NULL){
  193. cur_pin = atoi(token_plus);
  194. if(cur_pin || !strcmp(token_plus, "0")){
  195. int idx_cur_pin = get_idx_pin(gpio_pins, count_valid_gpios, cur_pin);
  196. if(idx_cur_pin == -1){
  197. READ_CONF_FILE_PRINTF(" Could not find GPIO: %s in previously instanciated GPIOs\n", token_plus);
  198. add_current_mapping = false;
  199. break;
  200. }
  201. cur_gpio_mapping.pins_idx[idx_pin] = idx_cur_pin;
  202. idx_pin++;
  203. READ_CONF_FILE_PRINTF(" GPIO %d in current mapping\n", cur_pin);
  204. }
  205. else{
  206. READ_CONF_FILE_PRINTF(" Could not find GPIO: %s\n", token_plus);
  207. add_current_mapping = false;
  208. break;
  209. }
  210. token_plus = strtok_r(NULL, "+", &end_arg);//strtok_r(NULL, ",");
  211. }
  212. cur_gpio_mapping.nb_simultaneous_pins = idx_pin;
  213. break;
  214. case MAPPING_ARG_TYPE:
  215. if(!strcmp(current_arg, "KEYBOARD")){
  216. cur_gpio_mapping.type_mapping = TYPE_MAPPING_KEYBOARD;
  217. }
  218. else if(!strcmp(current_arg, "SHELL_COMMAND")){
  219. cur_gpio_mapping.type_mapping = TYPE_MAPPING_SHELL_COMMAND;
  220. }
  221. else{
  222. READ_CONF_FILE_PRINTF(" %s is not a valid mapping type\n", current_arg);
  223. add_current_mapping = false;
  224. break;
  225. }
  226. break;
  227. case MAPPING_ARG_VALUE:
  228. switch (cur_gpio_mapping.type_mapping){
  229. case TYPE_MAPPING_KEYBOARD:
  230. cur_gpio_mapping.key_value = find_key(current_arg);
  231. if(!cur_gpio_mapping.key_value){
  232. READ_CONF_FILE_PRINTF(" Could not find Key: %s\n", current_arg);
  233. add_current_mapping = false;
  234. }
  235. break;
  236. case TYPE_MAPPING_SHELL_COMMAND:
  237. cur_gpio_mapping.shell_command = malloc(strlen(current_arg)*sizeof(char));
  238. strcpy(cur_gpio_mapping.shell_command, current_arg);
  239. break;
  240. default:
  241. READ_CONF_FILE_PRINTF(" %d is not a valid mapping type\n", cur_gpio_mapping.type_mapping);
  242. add_current_mapping = false;
  243. break;
  244. }
  245. break;
  246. case MAPPING_ARG_STR_HELP_PIN_NAME:
  247. if(!strlen(current_arg)) continue;
  248. cur_gpio_mapping.pin_help_str = malloc(strlen(current_arg)*sizeof(char));
  249. strcpy(cur_gpio_mapping.pin_help_str, current_arg);
  250. break;
  251. case MAPPING_ARG_STR_HELP_PIN_FCT:
  252. if(!strlen(current_arg)) continue;
  253. cur_gpio_mapping.fct_help_str = malloc(strlen(current_arg)*sizeof(char));
  254. strcpy(cur_gpio_mapping.fct_help_str, current_arg);
  255. break;
  256. default:
  257. break;
  258. }
  259. //next arg
  260. token_comma = strtok_r(NULL, ",", &end_ln);
  261. cur_arg_idx++;
  262. }
  263. if(add_current_mapping){
  264. push(&head_chained_list_mapping_gpio, &cur_gpio_mapping);
  265. READ_CONF_FILE_PRINTF("Current Mapping added successfully\n\n");
  266. }
  267. else{
  268. READ_CONF_FILE_PRINTF("Current Mapping not added\n\n");
  269. }
  270. }
  271. }
  272. }
  273. }
  274. READ_CONF_FILE_PRINTF("Sorting Chained list...\n");
  275. bubbleSort(head_chained_list_mapping_gpio);
  276. print_all_chained_list(head_chained_list_mapping_gpio);
  277. print_gpios(gpio_pins, count_valid_gpios);
  278. if(fp){
  279. fclose(fp);
  280. }
  281. /* Return parameters */
  282. *chained_list_mapping = head_chained_list_mapping_gpio;
  283. *nb_valid_gpios = count_valid_gpios;
  284. *valid_gpio_pins = gpio_pins;
  285. }
  286. /* Print all chained list content */
  287. void print_all_chained_list(STRUCT_MAPPED_GPIO * head){
  288. STRUCT_MAPPED_GPIO * current = head;
  289. int idx = 0;
  290. READ_CONF_FILE_PRINTF("Printing Chained list:\n ");
  291. while (current != NULL) {
  292. READ_CONF_FILE_PRINTF("Chained list Mapping GPIOs, idx: %d\n", idx);
  293. print_chained_list_node(current);
  294. idx++;
  295. current = current->next_mapped_gpio;
  296. }
  297. }
  298. /* Print one chained list node */
  299. void print_chained_list_node(STRUCT_MAPPED_GPIO * node){
  300. // Print Pins:
  301. if(node->nb_simultaneous_pins > 1){
  302. READ_CONF_FILE_PRINTF(" %d Simultaneous pins at following idx: [", node->nb_simultaneous_pins);
  303. int i;
  304. for (i=0; i < node->nb_simultaneous_pins; i++){
  305. READ_CONF_FILE_PRINTF("%d%s", node->pins_idx[i], (i==node->nb_simultaneous_pins-1)?"]\n":",");
  306. }
  307. }
  308. else{
  309. READ_CONF_FILE_PRINTF(" idx pin: %d\n", node->pins_idx[0]);
  310. }
  311. // Type mapping and Value
  312. if (node->type_mapping == TYPE_MAPPING_KEYBOARD){
  313. READ_CONF_FILE_PRINTF(" Type mapping: TYPE_MAPPING_KEYBOARD\n");
  314. READ_CONF_FILE_PRINTF(" Key: %d\n", node->key_value);
  315. }
  316. else if (node->type_mapping == TYPE_MAPPING_SHELL_COMMAND){
  317. READ_CONF_FILE_PRINTF(" Type mapping: TYPE_MAPPING_SHELL_COMMAND\n");
  318. READ_CONF_FILE_PRINTF(" Shell command: %s\n", node->shell_command);
  319. }
  320. // Pin help String
  321. if(node->pin_help_str[0]){
  322. READ_CONF_FILE_PRINTF(" Pins: %s\n", node->pin_help_str);
  323. }
  324. // Function help String
  325. if(node->fct_help_str[0]){
  326. READ_CONF_FILE_PRINTF(" Function: %s\n", node->fct_help_str);
  327. }
  328. }
  329. void print_gpios(int * valid_gpio_pins, int nb_valid_gpios){
  330. READ_CONF_FILE_PRINTF("GPIO pins:\n[");
  331. for(int i = 0; i< nb_valid_gpios; i++) {
  332. READ_CONF_FILE_PRINTF("%d%s", valid_gpio_pins[i], (i==nb_valid_gpios-1)?"]\n":",");
  333. }
  334. }