Home | History | Annotate | Download | only in linux
      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 
     15 enum 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 };
     23 static char sysfs_path[100];
     24 static char *chip_name[] = {
     25     "ITG3500",
     26     "MPU6050",
     27     "MPU9150",
     28     "MPU3050",
     29     "MPU6500",
     30     "MPU9250",
     31     "MPU6XXX",
     32     "MPU9350",
     33     "MPU6515",
     34 };
     35 static int chip_ind;
     36 static int initialized =0;
     37 static int status = 0;
     38 static int iio_initialized = 0;
     39 static 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 
     48 static 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  **/
     57 int 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  */
    112 static 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 }
    224 static 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 
    242 static 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 
    302 int 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  */
    401 inv_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  */
    417 inv_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 
    425 inv_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  */
    439 inv_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  */
    454 inv_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  */
    470 inv_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  */
    488 inv_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  */
    505 inv_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  */
    520 inv_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