Файлы System/bin Android 12. Справочник.


  Все     Команда     Скрипт     Служба     Приложение  

multi_ir - исходный текст
multi_ir.h
-----------------
#include <sys/stat.h>
#include <fcntl.h>
#ifndef __MULTI_IR_H__
#define __MULTI_IR_H__

#include <linux/ioctl.h>

/* ioctl cmd define */
#define MULTI_IR_IOC_MAGIC	'M'
/* return the max mapping table count support, if error, return -1 */
#define MULTI_IR_IOC_REQ_MAP	_IOR(MULTI_IR_IOC_MAGIC, 1, int *)
#define MULTI_IR_IOC_SET_MAP	_IOW(MULTI_IR_IOC_MAGIC, 2, void *)
#define MULTI_IR_IOC_CLR_MAP	_IOW(MULTI_IR_IOC_MAGIC, 3, int)

#define MAX_NAME_LEN	(32)
#define KEYCODE_MIN			(0)
#define KEYCODE_MAX			(255)
#define KEYCODE_CNT			(KEYCODE_MAX-KEYCODE_MIN+1)

/*
 A mapping table is mapping from customer ir key layout file(*.kl)
 to default layout file.

 For example:
	in coustomer kl file  -->  key 28  POWER
	in default kl file    -->  key 57  POWER

	then, the mapping will be like that: mapping_table.value[57] = 28
*/
struct mapping_table_t {
	int identity;				/* means ir address */
	int powerkey;				/* powerky to wakeup system */
	int value[KEYCODE_CNT];		/* convert from coustomer keycode to
                               default keycode */
};

#endif /* __MULTI_IR_H__ */


#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <ctype.h> #include <dirent.h> #include <sys/types.h> #include <sys/ioctl.h> #include <utils/Log.h> #include "multi_ir.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "multi_ir" #define RESERVE_CODE 0 #define RESERVE_NAME "!RESERVE" #undef DEBUG #define IR_DEV_PATH "/dev/sunxi-multi-ir" #define KEY_LAYOUT_PATH "/system/usr/keylayout" #define DEFAULT_KEYLAYOUT_FILE "sunxi-ir.kl" /* * A valid customer ir key layout file *MUST* namd by 'customer_ir_xxxx.kl', * which 'xxxx' is the identity(ir address code, in hex), * eg. customer_ir_9f00.kl */ #define FILENAME_PREFIX "customer_ir_" #define FILENAME_EXTENSION ".kl" struct keymap_t { int keycode; char name[MAX_NAME_LEN]; }; int mapping_table_cnt = 0; struct keymap_t default_keys[KEYCODE_CNT]; struct keymap_t customer_keys[KEYCODE_CNT]; struct mapping_table_t mapping_table; void keymap_init(struct keymap_t *map) { int i; for (i=0; i<KEYCODE_CNT; i++, map++) { map->keycode = RESERVE_CODE; strcpy(map->name, RESERVE_NAME); } } #ifdef DEBUG void dump_keymap(struct keymap_t *map) { int i; for (i=0; i<KEYCODE_CNT; i++, map++) { if (!strlen(map->name)) continue; printf("key\t%d\t%s\n", map->keycode, map->name); } } void dump_mapping_table(struct mapping_table_t *table, struct keymap_t *def) { int i; printf("+ identity: 0x%04x\n", table->identity); for (i=0; i<KEYCODE_CNT; i++) { printf("\t[%3d] --> { %3d, %-20s }\n", i, table->value[i], (def + table->value[i])->name); } } #endif /** * @brief: create a keymap form keylayout file(*.kl) * @param: path - path to the target file * @param: map - store the result * @return: */ int create_keymap_from_file(const char *path, struct keymap_t *map) { int ret = 0; FILE *kl_fd = NULL; char buf[1024], lable[32], name[MAX_NAME_LEN]; int keycode; char *p; struct keymap_t *des; kl_fd = fopen(path, "r"); if (!kl_fd) { fprintf(stderr, "open '%s' fail, %s\n", path, strerror(errno)); return -1; } while (fgets(buf, 1024, kl_fd)) { p = buf; while (*p==' ') p++; if (*p=='#') continue; if (sscanf(buf, "%s %d %s", lable, &keycode, name)!=3) continue; if (strcmp(lable, "key")!=0 || keycode < KEYCODE_MIN || keycode > KEYCODE_MAX) continue; des = (struct keymap_t *)(map + keycode); des->keycode = keycode; strcpy(des->name, name); } if (!feof(kl_fd)) { fprintf(stderr, "reading '%s' error, %s\n", path, strerror(errno)); ret = -1; } fclose(kl_fd); return ret; } /** * @brief: make a mapping from src to des, the result is store at @table, * the mapping will set to ir driver through ioctl syscall. * @param: src * @param: des * @param: table */ void generate_mapping_table(struct keymap_t* src, struct keymap_t *des, struct mapping_table_t *table) { int i, j; struct keymap_t *p; memset(table, 0, sizeof(struct mapping_table_t)); for (i=0; i<KEYCODE_CNT; i++, des++) { p = src; for (j=0; j<KEYCODE_CNT; j++, p++) { if (p->keycode==RESERVE_CODE) continue; if (strcmp(des->name, p->name)==0) { table->value[des->keycode] = p->keycode; if (table->powerkey==0 && strcmp(des->name, "POWER")==0) { table->powerkey = des->keycode; } break; } } } } /** * @brief: filter out the product model. * @param: name * @return: -1 means something error, else the product model. */ #define CMDLINE "/proc/cmdline" int get_product_model(char model[]) { FILE * fp; char buf[1024] = {0}; char *str = NULL; fp = fopen(CMDLINE, "r"); if (NULL == fp) { printf("open %s failed!\n",CMDLINE); return -1; } if(!fread(buf, 1, 1024, fp)) { printf("read file filed!\n"); return -1; } if((str = strstr(buf, "inside_model")) == NULL) { printf("get model failed!\n"); return -1; } //printf("str= %s\n", str); str = str + strlen("inside_model="); while((*model++ = *str++) != ' '); *(model - 1) = '\0'; fclose(fp); return 0; } /** * @brief: filter out the valid kaylaout file. * @param: name * @return: -1 means something error, else the identity. */ int kl_filename_verify(const char *name, char model[]) { char *p; int i, identity; /* filename prefix filter */ if (strncmp(name, FILENAME_PREFIX, strlen(FILENAME_PREFIX))) return -1; /* product model filter */ if (strlen(model) != 0) { // too many product, support default 7 customer kl if (!strncmp(model, "CanC", 4) || !strncmp(model, "AMOI_B", 6) || !strncmp(model, "EARISE_K", 8)) { p = (char *)name + strlen(FILENAME_PREFIX) + 4; if (strncmp(p, FILENAME_EXTENSION, strlen(FILENAME_EXTENSION))) return -1; //printf("product model= %s, file name = %s \n",model,name); } else { p = (char *)name + strlen(FILENAME_PREFIX) + 5; //printf("get %s product model %s, %s, %d\n",name,model,p,strlen(model)); if (!strncmp(p, model, strlen(model))) { /* model matched, filename extensiion filter */ p = (char *)name + strlen(name) - 3; if (strncmp(p, FILENAME_EXTENSION, strlen(FILENAME_EXTENSION))) return -1; } else { /* model is not match, use default 4cb3 customer kl */ p = (char *)name + strlen(FILENAME_PREFIX); if (strncmp(p, "4cb3", 4) && strncmp(p, "fe01", 4)) return -1; p = (char *)name + strlen(FILENAME_PREFIX) + 4; if (strncmp(p, FILENAME_EXTENSION, strlen(FILENAME_EXTENSION))) return -1; } } } else { /* filename extensiion filter */ p = (char *)name + strlen(FILENAME_PREFIX) + 4; if (strncmp(p, FILENAME_EXTENSION, strlen(FILENAME_EXTENSION))) return -1; } /* identity filter, 4 hexadecimal number */ p = (char *)name + strlen(FILENAME_PREFIX); for (i=0; i<4; i++) { if (isxdigit(*(p+i))==0) return -1; } ALOGD("----%s------------------\n", p); identity = strtol(p, &p, 16); ALOGD("----%s--------------0x%x----\n", p, identity); return identity; } int main(int argc, char **argv) { int dev_fd, ret = 0; char kl_path[512] = {0}; DIR *dir; struct dirent *dirent; int identity; dev_fd = open(IR_DEV_PATH, O_RDWR); if (dev_fd<0) { fprintf(stderr, "Open device '%s' error\n", IR_DEV_PATH); exit(-1); } if (ioctl(dev_fd, MULTI_IR_IOC_REQ_MAP, &mapping_table_cnt)<0) { fprintf(stderr, "ioctl 'MULTI_IR_IOC_REQ_MAP' error\n"); ret = -1; goto err_ioctl; } if (mapping_table_cnt<=0) { fprintf(stderr, "sunxi ir driver is to old to support multi mode\n "); ret = -1; goto err_ioctl; } ALOGD("the max mapping_table support by driver: %d\n", mapping_table_cnt); /* create default key map */ keymap_init(default_keys); sprintf(kl_path, "%s/%s", KEY_LAYOUT_PATH, DEFAULT_KEYLAYOUT_FILE); create_keymap_from_file(kl_path, default_keys); #ifdef DEBUG dump_keymap(default_keys); #endif dir = opendir(KEY_LAYOUT_PATH); if (!dir) { fprintf(stderr, "Open directory '%s' error, %s\n", KEY_LAYOUT_PATH, strerror(errno)); exit(-1); } char model[32]={0}; get_product_model(model); while ((dirent=readdir(dir))!=NULL) { identity = kl_filename_verify(dirent->d_name, model); if (identity!=-1) { ALOGD("config filename %s\n", dirent->d_name); sprintf(kl_path, "%s/%s", KEY_LAYOUT_PATH, dirent->d_name); memset(customer_keys, 0, sizeof(struct keymap_t)*(KEYCODE_CNT)); create_keymap_from_file(kl_path, customer_keys); generate_mapping_table(default_keys, customer_keys, &mapping_table); mapping_table.identity = identity; #ifdef DEBUG dump_mapping_table(&mapping_table, default_keys); #endif if (ioctl(dev_fd, MULTI_IR_IOC_SET_MAP, &mapping_table)<0) { fprintf(stderr, "ioctl 'MULTI_IR_IOC_SET_MAP' error, identity: 0x%04x\n", identity); ret = -1; break; } } } closedir(dir); err_ioctl: close(dev_fd); return ret; }