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