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