1#include <string.h> 2#include <stdio.h> 3#include "ml_sysfs_helper.h" 4#include <dirent.h> 5#include <ctype.h> 6#define MPU_SYSFS_ABS_PATH "/sys/class/invensense/mpu" 7 8enum PROC_SYSFS_CMD { 9 CMD_GET_SYSFS_PATH, 10 CMD_GET_DMP_PATH, 11 CMD_GET_CHIP_NAME, 12 CMD_GET_SYSFS_KEY, 13 CMD_GET_TRIGGER_PATH, 14 CMD_GET_DEVICE_NODE 15}; 16static char sysfs_path[100]; 17static char *chip_name[] = { 18 "ITG3500", 19 "MPU6050", 20 "MPU9150", 21 "MPU3050", 22 "MPU6500" 23}; 24static int chip_ind; 25static int initialized =0; 26static int status = 0; 27static int iio_initialized = 0; 28static int iio_dev_num = 0; 29 30#define IIO_MAX_NAME_LENGTH 30 31 32#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" 33#define FORMAT_TYPE_FILE "%s_type" 34 35#define CHIP_NUM ARRAY_SIZE(chip_name) 36 37static const char *iio_dir = "/sys/bus/iio/devices/"; 38 39/** 40 * find_type_by_name() - function to match top level types by name 41 * @name: top level type instance name 42 * @type: the type of top level instance being sort 43 * 44 * Typical types this is used for are device and trigger. 45 **/ 46int find_type_by_name(const char *name, const char *type) 47{ 48 const struct dirent *ent; 49 int number, numstrlen; 50 51 FILE *nameFile; 52 DIR *dp; 53 char thisname[IIO_MAX_NAME_LENGTH]; 54 char *filename; 55 56 dp = opendir(iio_dir); 57 if (dp == NULL) { 58 printf("No industrialio devices available"); 59 return -ENODEV; 60 } 61 62 while (ent = readdir(dp), ent != NULL) { 63 if (strcmp(ent->d_name, ".") != 0 && 64 strcmp(ent->d_name, "..") != 0 && 65 strlen(ent->d_name) > strlen(type) && 66 strncmp(ent->d_name, type, strlen(type)) == 0) { 67 numstrlen = sscanf(ent->d_name + strlen(type), 68 "%d", 69 &number); 70 /* verify the next character is not a colon */ 71 if (strncmp(ent->d_name + strlen(type) + numstrlen, 72 ":", 73 1) != 0) { 74 filename = malloc(strlen(iio_dir) 75 + strlen(type) 76 + numstrlen 77 + 6); 78 if (filename == NULL) 79 return -ENOMEM; 80 sprintf(filename, "%s%s%d/name", 81 iio_dir, 82 type, 83 number); 84 nameFile = fopen(filename, "r"); 85 if (!nameFile) 86 continue; 87 free(filename); 88 fscanf(nameFile, "%s", thisname); 89 if (strcmp(name, thisname) == 0) 90 return number; 91 fclose(nameFile); 92 } 93 } 94 } 95 return -ENODEV; 96} 97 98/* mode 0: search for which chip in the system and fill sysfs path 99 mode 1: return event number 100 */ 101static int parsing_proc_input(int mode, char *name){ 102 const char input[] = "/proc/bus/input/devices"; 103 char line[4096], d; 104 char tmp[100]; 105 FILE *fp; 106 int i, j, result, find_flag; 107 int event_number = -1; 108 int input_number = -1; 109 110 if(NULL == (fp = fopen(input, "rt")) ){ 111 return -1; 112 } 113 result = 1; 114 find_flag = 0; 115 while(result != 0 && find_flag < 2){ 116 i = 0; 117 d = 0; 118 memset(line, 0, 100); 119 while(d != '\n'){ 120 result = fread(&d, 1, 1, fp); 121 if(result == 0){ 122 line[0] = 0; 123 break; 124 } 125 sprintf(&line[i], "%c", d); 126 i ++; 127 } 128 if(line[0] == 'N'){ 129 i = 1; 130 while(line[i] != '"'){ 131 i++; 132 } 133 i++; 134 j = 0; 135 find_flag = 0; 136 if (mode == 0){ 137 while(j < CHIP_NUM){ 138 if(!memcmp(&line[i], chip_name[j], strlen(chip_name[j]))){ 139 find_flag = 1; 140 chip_ind = j; 141 } 142 j++; 143 } 144 } else if (mode != 0){ 145 if(!memcmp(&line[i], name, strlen(name))){ 146 find_flag = 1; 147 } 148 } 149 } 150 if(find_flag){ 151 if(mode == 0){ 152 if(line[0] == 'S'){ 153 memset(tmp, 0, 100); 154 i =1; 155 while(line[i] != '=') i++; 156 i++; 157 j = 0; 158 while(line[i] != '\n'){ 159 tmp[j] = line[i]; 160 i ++; j++; 161 } 162 sprintf(sysfs_path, "%s%s", "/sys", tmp); 163 find_flag++; 164 } 165 } else if(mode == 1){ 166 if(line[0] == 'H') { 167 i = 2; 168 while(line[i] != '=') i++; 169 while(line[i] != 't') i++; 170 i++; 171 event_number = 0; 172 while(line[i] != '\n'){ 173 if(line[i] >= '0' && line[i] <= '9') 174 event_number = event_number*10 + line[i]-0x30; 175 i ++; 176 } 177 find_flag ++; 178 } 179 } else if (mode == 2) { 180 if(line[0] == 'S'){ 181 memset(tmp, 0, 100); 182 i =1; 183 while(line[i] != '=') i++; 184 i++; 185 j = 0; 186 while(line[i] != '\n'){ 187 tmp[j] = line[i]; 188 i ++; j++; 189 } 190 input_number = 0; 191 if(tmp[j-2] >= '0' && tmp[j-2] <= '9') 192 input_number += (tmp[j-2]-0x30)*10; 193 if(tmp[j-1] >= '0' && tmp[j-1] <= '9') 194 input_number += (tmp[j-1]-0x30); 195 find_flag++; 196 } 197 } 198 } 199 } 200 fclose(fp); 201 if(find_flag == 0){ 202 return -1; 203 } 204 if(0 == mode) 205 status = 1; 206 if (mode == 1) 207 return event_number; 208 if (mode == 2) 209 return input_number; 210 return 0; 211 212} 213static void init_iio() { 214 int i, j; 215 char iio_chip[10]; 216 int dev_num; 217 for(j=0; j< CHIP_NUM; j++) { 218 for (i=0; i<strlen(chip_name[j]); i++) { 219 iio_chip[i] = tolower(chip_name[j][i]); 220 } 221 iio_chip[strlen(chip_name[0])] = '\0'; 222 dev_num = find_type_by_name(iio_chip, "iio:device"); 223 if(dev_num >= 0) { 224 iio_initialized = 1; 225 iio_dev_num = dev_num; 226 chip_ind = j; 227 } 228 } 229} 230 231static int process_sysfs_request(enum PROC_SYSFS_CMD cmd, char *data) 232{ 233 char key_path[100]; 234 FILE *fp; 235 int i, result; 236 if(initialized == 0){ 237 parsing_proc_input(0, NULL); 238 initialized = 1; 239 } 240 if(initialized && status == 0) { 241 init_iio(); 242 if (iio_initialized == 0) 243 return -1; 244 } 245 246 memset(key_path, 0, 100); 247 switch(cmd){ 248 case CMD_GET_SYSFS_PATH: 249 if (iio_initialized == 1) 250 sprintf(data, "/sys/bus/iio/devices/iio:device%d", iio_dev_num); 251 else 252 sprintf(data, "%s%s", sysfs_path, "/device/invensense/mpu"); 253 break; 254 case CMD_GET_DMP_PATH: 255 if (iio_initialized == 1) 256 sprintf(data, "/sys/bus/iio/devices/iio:device%d/dmp_firmware", iio_dev_num); 257 else 258 sprintf(data, "%s%s", sysfs_path, "/device/invensense/mpu/dmp_firmware"); 259 break; 260 case CMD_GET_CHIP_NAME: 261 sprintf(data, "%s", chip_name[chip_ind]); 262 break; 263 case CMD_GET_TRIGGER_PATH: 264 sprintf(data, "/sys/bus/iio/devices/trigger%d", iio_dev_num); 265 break; 266 case CMD_GET_DEVICE_NODE: 267 sprintf(data, "/dev/iio:device%d", iio_dev_num); 268 break; 269 case CMD_GET_SYSFS_KEY: 270 memset(key_path, 0, 100); 271 if (iio_initialized == 1) 272 sprintf(key_path, "/sys/bus/iio/devices/iio:device%d/key", iio_dev_num); 273 else 274 sprintf(key_path, "%s%s", sysfs_path, "/device/invensense/mpu/key"); 275 276 if((fp = fopen(key_path, "rt")) == NULL) 277 return -1; 278 for(i=0;i<16;i++){ 279 fscanf(fp, "%02x", &result); 280 data[i] = (char)result; 281 } 282 283 fclose(fp); 284 break; 285 default: 286 break; 287 } 288 return 0; 289} 290/** 291 * @brief return sysfs key. if the key is not available 292 * return false. So the return value must be checked 293 * to make sure the path is valid. 294 * @unsigned char *name: This should be array big enough to hold the key 295 * It should be zeroed before calling this function. 296 * Or it could have unpredicable result. 297 */ 298inv_error_t inv_get_sysfs_key(unsigned char *key) 299{ 300 if (process_sysfs_request(CMD_GET_SYSFS_KEY, (char*)key) < 0) 301 return INV_ERROR_NOT_OPENED; 302 else 303 return INV_SUCCESS; 304} 305 306/** 307 * @brief return the sysfs path. If the path is not 308 * found yet. return false. So the return value must be checked 309 * to make sure the path is valid. 310 * @unsigned char *name: This should be array big enough to hold the sysfs 311 * path. It should be zeroed before calling this function. 312 * Or it could have unpredicable result. 313 */ 314inv_error_t inv_get_sysfs_path(char *name) 315{ 316 if (process_sysfs_request(CMD_GET_SYSFS_PATH, name) < 0) 317 return INV_ERROR_NOT_OPENED; 318 else 319 return INV_SUCCESS; 320} 321 322inv_error_t inv_get_sysfs_abs_path(char *name) 323{ 324 strcpy(name, MPU_SYSFS_ABS_PATH); 325 return INV_SUCCESS; 326} 327 328/** 329 * @brief return the dmp file path. If the path is not 330 * found yet. return false. So the return value must be checked 331 * to make sure the path is valid. 332 * @unsigned char *name: This should be array big enough to hold the dmp file 333 * path. It should be zeroed before calling this function. 334 * Or it could have unpredicable result. 335 */ 336inv_error_t inv_get_dmpfile(char *name) 337{ 338 if (process_sysfs_request(CMD_GET_DMP_PATH, name) < 0) 339 return INV_ERROR_NOT_OPENED; 340 else 341 return INV_SUCCESS; 342} 343/** 344 * @brief return the chip name. If the chip is not 345 * found yet. return false. So the return value must be checked 346 * to make sure the path is valid. 347 * @unsigned char *name: This should be array big enough to hold the chip name 348 * path(8 bytes). It should be zeroed before calling this function. 349 * Or it could have unpredicable result. 350 */ 351inv_error_t inv_get_chip_name(char *name) 352{ 353 if (process_sysfs_request(CMD_GET_CHIP_NAME, name) < 0) 354 return INV_ERROR_NOT_OPENED; 355 else 356 return INV_SUCCESS; 357} 358/** 359 * @brief return event handler number. If the handler number is not found 360 * return false. the return value must be checked 361 * to make sure the path is valid. 362 * @unsigned char *name: This should be array big enough to hold the chip name 363 * path(8 bytes). It should be zeroed before calling this function. 364 * Or it could have unpredicable result. 365 * @int *num: event number store 366 */ 367inv_error_t inv_get_handler_number(const char *name, int *num) 368{ 369 initialized = 0; 370 if ((*num = parsing_proc_input(1, (char *)name)) < 0) 371 return INV_ERROR_NOT_OPENED; 372 else 373 return INV_SUCCESS; 374} 375 376/** 377 * @brief return input number. If the handler number is not found 378 * return false. the return value must be checked 379 * to make sure the path is valid. 380 * @unsigned char *name: This should be array big enough to hold the chip name 381 * path(8 bytes). It should be zeroed before calling this function. 382 * Or it could have unpredicable result. 383 * @int *num: input number store 384 */ 385inv_error_t inv_get_input_number(const char *name, int *num) 386{ 387 initialized = 0; 388 if ((*num = parsing_proc_input(2, (char *)name)) < 0) 389 return INV_ERROR_NOT_OPENED; 390 else { 391 return INV_SUCCESS; 392 } 393} 394 395/** 396 * @brief return iio trigger name. If iio is not initialized, return false. 397 * So the return must be checked to make sure the numeber is valid. 398 * @unsigned char *name: This should be array big enough to hold the trigger 399 * name. It should be zeroed before calling this function. 400 * Or it could have unpredicable result. 401 */ 402inv_error_t inv_get_iio_trigger_path(char *name) 403{ 404 if (process_sysfs_request(CMD_GET_TRIGGER_PATH, (char *)name) < 0) 405 return INV_ERROR_NOT_OPENED; 406 else 407 return INV_SUCCESS; 408} 409 410/** 411 * @brief return iio device node. If iio is not initialized, return false. 412 * So the return must be checked to make sure the numeber is valid. 413 * @unsigned char *name: This should be array big enough to hold the device 414 * node. It should be zeroed before calling this function. 415 * Or it could have unpredicable result. 416 */ 417inv_error_t inv_get_iio_device_node(char *name) 418{ 419 if (process_sysfs_request(CMD_GET_DEVICE_NODE, (char *)name) < 0) 420 return INV_ERROR_NOT_OPENED; 421 else 422 return INV_SUCCESS; 423} 424