Home | History | Annotate | Download | only in linux
      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 
      8 enum 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 };
     16 static char sysfs_path[100];
     17 static char *chip_name[] = {
     18     "ITG3500",
     19     "MPU6050",
     20     "MPU9150",
     21     "MPU3050",
     22     "MPU6500"
     23 };
     24 static int chip_ind;
     25 static int initialized =0;
     26 static int status = 0;
     27 static int iio_initialized = 0;
     28 static 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 
     37 static 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  **/
     46 int 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  */
    101 static 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 }
    213 static 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 
    231 static 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  */
    298 inv_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  */
    314 inv_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 
    322 inv_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  */
    336 inv_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  */
    351 inv_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  */
    367 inv_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  */
    385 inv_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  */
    402 inv_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  */
    417 inv_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