ml_sysfs_helper.c revision 33ce91b37062fa63af192f5643de93f3beebe854
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 8enum 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}; 16static char sysfs_path[100]; 17static char *chip_name[] = {"ITG3500", "MPU6050", "MPU9150", "MPU3050", "MPU6500"}; 18static int chip_ind; 19static int initialized =0; 20static int status = 0; 21static int iio_initialized = 0; 22static int iio_dev_num = 0; 23 24#define IIO_MAX_NAME_LENGTH 30 25 26#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" 27#define FORMAT_TYPE_FILE "%s_type" 28 29#define CHIP_NUM sizeof(chip_name)/sizeof(char*) 30 31static const char *iio_dir = "/sys/bus/iio/devices/"; 32 33/** 34 * find_type_by_name() - function to match top level types by name 35 * @name: top level type instance name 36 * @type: the type of top level instance being sort 37 * 38 * Typical types this is used for are device and trigger. 39 **/ 40int find_type_by_name(const char *name, const char *type) 41{ 42 const struct dirent *ent; 43 int number, numstrlen; 44 45 FILE *nameFile; 46 DIR *dp; 47 char thisname[IIO_MAX_NAME_LENGTH]; 48 char *filename; 49 50 dp = opendir(iio_dir); 51 if (dp == NULL) { 52 printf("No industrialio devices available"); 53 return -ENODEV; 54 } 55 56 while (ent = readdir(dp), ent != NULL) { 57 if (strcmp(ent->d_name, ".") != 0 && 58 strcmp(ent->d_name, "..") != 0 && 59 strlen(ent->d_name) > strlen(type) && 60 strncmp(ent->d_name, type, strlen(type)) == 0) { 61 numstrlen = sscanf(ent->d_name + strlen(type), 62 "%d", 63 &number); 64 /* verify the next character is not a colon */ 65 if (strncmp(ent->d_name + strlen(type) + numstrlen, 66 ":", 67 1) != 0) { 68 filename = malloc(strlen(iio_dir) 69 + strlen(type) 70 + numstrlen 71 + 6); 72 if (filename == NULL) 73 return -ENOMEM; 74 sprintf(filename, "%s%s%d/name", 75 iio_dir, 76 type, 77 number); 78 nameFile = fopen(filename, "r"); 79 if (!nameFile) 80 continue; 81 free(filename); 82 fscanf(nameFile, "%s", thisname); 83 if (strcmp(name, thisname) == 0) 84 return number; 85 fclose(nameFile); 86 } 87 } 88 } 89 return -ENODEV; 90} 91 92/* mode 0: search for which chip in the system and fill sysfs path 93 mode 1: return event number 94 */ 95static int parsing_proc_input(int mode, char *name){ 96 const char input[] = "/proc/bus/input/devices"; 97 char line[100], d; 98 char tmp[100]; 99 FILE *fp; 100 int i, j, result, find_flag; 101 int event_number = -1; 102 int input_number = -1; 103 104 if(NULL == (fp = fopen(input, "rt")) ){ 105 return -1; 106 } 107 result = 1; 108 find_flag = 0; 109 while(result != 0 && find_flag < 2){ 110 i = 0; 111 d = 0; 112 memset(line, 0, 100); 113 while(d != '\n'){ 114 result = fread(&d, 1, 1, fp); 115 if(result == 0){ 116 line[0] = 0; 117 break; 118 } 119 sprintf(&line[i], "%c", d); 120 i ++; 121 } 122 if(line[0] == 'N'){ 123 i = 1; 124 while(line[i] != '"'){ 125 i++; 126 } 127 i++; 128 j = 0; 129 find_flag = 0; 130 if (mode == 0){ 131 while(j < CHIP_NUM){ 132 if(!memcmp(&line[i], chip_name[j], strlen(chip_name[j]))){ 133 find_flag = 1; 134 chip_ind = j; 135 } 136 j++; 137 } 138 } else if (mode != 0){ 139 if(!memcmp(&line[i], name, strlen(name))){ 140 find_flag = 1; 141 } 142 } 143 } 144 if(find_flag){ 145 if(mode == 0){ 146 if(line[0] == 'S'){ 147 memset(tmp, 0, 100); 148 i =1; 149 while(line[i] != '=') i++; 150 i++; 151 j = 0; 152 while(line[i] != '\n'){ 153 tmp[j] = line[i]; 154 i ++; j++; 155 } 156 sprintf(sysfs_path, "%s%s", "/sys", tmp); 157 find_flag++; 158 } 159 } else if(mode == 1){ 160 if(line[0] == 'H') { 161 i = 2; 162 while(line[i] != '=') i++; 163 while(line[i] != 't') i++; 164 i++; 165 event_number = 0; 166 while(line[i] != '\n'){ 167 if(line[i] >= '0' && line[i] <= '9') 168 event_number = event_number*10 + line[i]-0x30; 169 i ++; 170 } 171 find_flag ++; 172 } 173 } else if (mode == 2) { 174 if(line[0] == 'S'){ 175 memset(tmp, 0, 100); 176 i =1; 177 while(line[i] != '=') i++; 178 i++; 179 j = 0; 180 while(line[i] != '\n'){ 181 tmp[j] = line[i]; 182 i ++; j++; 183 } 184 input_number = 0; 185 if(tmp[j-2] >= '0' && tmp[j-2] <= '9') 186 input_number += (tmp[j-2]-0x30)*10; 187 if(tmp[j-1] >= '0' && tmp[j-1] <= '9') 188 input_number += (tmp[j-1]-0x30); 189 find_flag++; 190 } 191 } 192 } 193 } 194 fclose(fp); 195 if(find_flag == 0){ 196 return -1; 197 } 198 if(0 == mode) 199 status = 1; 200 if (mode == 1) 201 return event_number; 202 if (mode == 2) 203 return input_number; 204 return 0; 205 206} 207static void init_iio() { 208 int i, j; 209 char iio_chip[10]; 210 int dev_num; 211 for(j=0; j< CHIP_NUM; j++) { 212 for (i=0; i<strlen(chip_name[j]); i++) { 213 iio_chip[i] = tolower(chip_name[j][i]); 214 } 215 iio_chip[strlen(chip_name[0])] = '\0'; 216 dev_num = find_type_by_name(iio_chip, "iio:device"); 217 if(dev_num >= 0) { 218 iio_initialized = 1; 219 iio_dev_num = dev_num; 220 chip_ind = j; 221 } 222 } 223} 224 225static int process_sysfs_request(enum PROC_SYSFS_CMD cmd, char *data) 226{ 227 char key_path[100]; 228 FILE *fp; 229 int i, result; 230 if(initialized == 0){ 231 parsing_proc_input(0, NULL); 232 initialized = 1; 233 } 234 if(initialized && status == 0) { 235 init_iio(); 236 if (iio_initialized == 0) 237 return -1; 238 } 239 240 memset(key_path, 0, 100); 241 switch(cmd){ 242 case CMD_GET_SYSFS_PATH: 243 if (iio_initialized == 1) 244 sprintf(data, "/sys/bus/iio/devices/iio:device%d", iio_dev_num); 245 else 246 sprintf(data, "%s%s", sysfs_path, "/device/invensense/mpu"); 247 break; 248 case CMD_GET_DMP_PATH: 249 if (iio_initialized == 1) 250 sprintf(data, "/sys/bus/iio/devices/iio:device%d/dmp_firmware", iio_dev_num); 251 else 252 sprintf(data, "%s%s", sysfs_path, "/device/invensense/mpu/dmp_firmware"); 253 break; 254 case CMD_GET_CHIP_NAME: 255 sprintf(data, "%s", chip_name[chip_ind]); 256 break; 257 case CMD_GET_TRIGGER_PATH: 258 sprintf(data, "/sys/bus/iio/devices/trigger%d", iio_dev_num); 259 break; 260 case CMD_GET_DEVICE_NODE: 261 sprintf(data, "/dev/iio:device%d", iio_dev_num); 262 break; 263 case CMD_GET_SYSFS_KEY: 264 memset(key_path, 0, 100); 265 if (iio_initialized == 1) 266 sprintf(key_path, "/sys/bus/iio/devices/iio:device%d/key", iio_dev_num); 267 else 268 sprintf(key_path, "%s%s", sysfs_path, "/device/invensense/mpu/key"); 269 270 if((fp = fopen(key_path, "rt")) == NULL) 271 return -1; 272 for(i=0;i<16;i++){ 273 fscanf(fp, "%02x", &result); 274 data[i] = (char)result; 275 } 276 277 fclose(fp); 278 break; 279 default: 280 break; 281 } 282 return 0; 283} 284/** 285 * @brief return sysfs key. if the key is not available 286 * return false. So the return value must be checked 287 * to make sure the path is valid. 288 * @unsigned char *name: This should be array big enough to hold the key 289 * It should be zeroed before calling this function. 290 * Or it could have unpredicable result. 291 */ 292inv_error_t inv_get_sysfs_key(unsigned char *key) 293{ 294 if (process_sysfs_request(CMD_GET_SYSFS_KEY, (char*)key) < 0) 295 return INV_ERROR_NOT_OPENED; 296 else 297 return INV_SUCCESS; 298} 299 300/** 301 * @brief return the sysfs path. If the path is not 302 * found yet. return false. So the return value must be checked 303 * to make sure the path is valid. 304 * @unsigned char *name: This should be array big enough to hold the sysfs 305 * path. It should be zeroed before calling this function. 306 * Or it could have unpredicable result. 307 */ 308inv_error_t inv_get_sysfs_path(char *name) 309{ 310 if (process_sysfs_request(CMD_GET_SYSFS_PATH, name) < 0) 311 return INV_ERROR_NOT_OPENED; 312 else 313 return INV_SUCCESS; 314} 315 316inv_error_t inv_get_sysfs_abs_path(char *name) 317{ 318 strcpy(name, MPU_SYSFS_ABS_PATH); 319 return INV_SUCCESS; 320} 321 322/** 323 * @brief return the dmp file path. If the path is not 324 * found yet. return false. So the return value must be checked 325 * to make sure the path is valid. 326 * @unsigned char *name: This should be array big enough to hold the dmp file 327 * path. It should be zeroed before calling this function. 328 * Or it could have unpredicable result. 329 */ 330inv_error_t inv_get_dmpfile(char *name) 331{ 332 if (process_sysfs_request(CMD_GET_DMP_PATH, name) < 0) 333 return INV_ERROR_NOT_OPENED; 334 else 335 return INV_SUCCESS; 336} 337/** 338 * @brief return the chip name. If the chip is not 339 * found yet. return false. So the return value must be checked 340 * to make sure the path is valid. 341 * @unsigned char *name: This should be array big enough to hold the chip name 342 * path(8 bytes). It should be zeroed before calling this function. 343 * Or it could have unpredicable result. 344 */ 345inv_error_t inv_get_chip_name(char *name) 346{ 347 if (process_sysfs_request(CMD_GET_CHIP_NAME, name) < 0) 348 return INV_ERROR_NOT_OPENED; 349 else 350 return INV_SUCCESS; 351} 352/** 353 * @brief return event handler number. If the handler number is not found 354 * return false. the return value must be checked 355 * to make sure the path is valid. 356 * @unsigned char *name: This should be array big enough to hold the chip name 357 * path(8 bytes). It should be zeroed before calling this function. 358 * Or it could have unpredicable result. 359 * @int *num: event number store 360 */ 361inv_error_t inv_get_handler_number(const char *name, int *num) 362{ 363 initialized = 0; 364 if ((*num = parsing_proc_input(1, (char *)name)) < 0) 365 return INV_ERROR_NOT_OPENED; 366 else 367 return INV_SUCCESS; 368} 369 370/** 371 * @brief return input number. If the handler number is not found 372 * return false. the return value must be checked 373 * to make sure the path is valid. 374 * @unsigned char *name: This should be array big enough to hold the chip name 375 * path(8 bytes). It should be zeroed before calling this function. 376 * Or it could have unpredicable result. 377 * @int *num: input number store 378 */ 379inv_error_t inv_get_input_number(const char *name, int *num) 380{ 381 initialized = 0; 382 if ((*num = parsing_proc_input(2, (char *)name)) < 0) 383 return INV_ERROR_NOT_OPENED; 384 else { 385 return INV_SUCCESS; 386 } 387} 388 389/** 390 * @brief return iio trigger name. If iio is not initialized, return false. 391 * So the return must be checked to make sure the numeber is valid. 392 * @unsigned char *name: This should be array big enough to hold the trigger 393 * name. It should be zeroed before calling this function. 394 * Or it could have unpredicable result. 395 */ 396inv_error_t inv_get_iio_trigger_path(char *name) 397{ 398 if (process_sysfs_request(CMD_GET_TRIGGER_PATH, (char *)name) < 0) 399 return INV_ERROR_NOT_OPENED; 400 else 401 return INV_SUCCESS; 402} 403 404/** 405 * @brief return iio device node. If iio is not initialized, return false. 406 * So the return must be checked to make sure the numeber is valid. 407 * @unsigned char *name: This should be array big enough to hold the device 408 * node. It should be zeroed before calling this function. 409 * Or it could have unpredicable result. 410 */ 411inv_error_t inv_get_iio_device_node(char *name) 412{ 413 if (process_sysfs_request(CMD_GET_DEVICE_NODE, (char *)name) < 0) 414 return INV_ERROR_NOT_OPENED; 415 else 416 return INV_SUCCESS; 417} 418