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