링크 ux 장치 모델 의 input 서브 시스템

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
전재 출처 를 밝 혀 주 십시오:http://blog.csdn.net/gdt_A20
==================================
요약:
input 서브 시스템 은 kernel 에서 비교적 간단 한 서브 시스템 으로 주로 입력 장치 (터치 스크린, 키보드 등) 를 관리 하 는 데 사 용 됩 니 다. 개인 적 으로 driver 의 출발점 이 될 수 있다 고 생각 합 니 다. 입력 장치 가 생각 하지 않 고 입력 정 보 를 제공 해 야 합 니 다. input 서브 시스템 은 이런 정 보 를 사건 으로 삼 아 구분 하고 실시 간 으로 업로드 합 니 다!input 에서 그렇게 규칙 적 이지 않 고 버스 의 개념 (하드웨어 에 존재 하지 않 음) 을 추상 화하 지 않 고 하나의 구조 struct inputhandle 가 버스 를 충당 했다.
struct input_handle 연결 작업 구조 및 장치, input 장치 용 struct inputdev 구 조 는 조작 함 수 를 struct input 로 표시 합 니 다.handler
자, 여기 inputhandle 와 inputhandler 비슷 합 니 다. 전역 적 인 input 장치 링크 input 가 존재 합 니 다.dev_list, 모든 input 장 치 를 연결 하 는 데 사용,
전역 적 인 input 작업 체인 테이블 input 존재handler_list, 모든 handler 를 연결 하 는 데 사용 합 니 다.
주요 디렉토리: drivers / input
struct input_dev
관련 데이터 구조
1.input device
   
struct input_dev {
	const char *name;               //  
	const char *phys;               //    
	const char *uniq;               //       
	struct input_id id;             //  id

	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];  //        

	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];            //     
	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];          //key,button  
	unsigned long relbit[BITS_TO_LONGS(REL_CNT)];          //    
	unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];          //    
	unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];          //      
	unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];          //led  
	unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];          //      
	unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
	unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

	unsigned int hint_events_per_packet;

	unsigned int keycodemax;                              //     
	unsigned int keycodesize;                             
	void *keycode;                                        //     

	int (*setkeycode)(struct input_dev *dev,              //      
			  const struct input_keymap_entry *ke,
			  unsigned int *old_keycode);
	int (*getkeycode)(struct input_dev *dev,
			  struct input_keymap_entry *ke);

	struct ff_device *ff;

	unsigned int repeat_key;
	struct timer_list timer;                             //   

	int rep[REP_CNT];

	struct input_mt_slot *mt;
	int mtsize;
	int slot;
	int trkid;

	struct input_absinfo *absinfo;

	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
	unsigned long led[BITS_TO_LONGS(LED_CNT)];
	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
	unsigned long sw[BITS_TO_LONGS(SW_CNT)];

	int (*open)(struct input_dev *dev);                 //open    
	void (*close)(struct input_dev *dev);
	int (*flush)(struct input_dev *dev, struct file *file);
	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

	struct input_handle __rcu *grab;

	spinlock_t event_lock;
	struct mutex mutex;

	unsigned int users;
	bool going_away;

	bool sync;

	struct device dev;                                  //devices   

	struct list_head	h_list;                    //     handle
	struct list_head	node;                      //     input_dev_list
};
2. 조작 함수 구조 inputhandler
struct input_handler {

	void *private;                            //      

	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
	bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
	bool (*match)(struct input_handler *handler, struct input_dev *dev);
	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
	void (*disconnect)(struct input_handle *handle);
	void (*start)(struct input_handle *handle);

	const struct file_operations *fops;
	int minor;
	const char *name;                          //  

	const struct input_device_id *id_table;    //   devices,id 

	struct list_head	h_list;   //        handle 
	struct list_head	node;     //        input_handler_list  
};
3. bus 의 충당 자 전체 관리 구조
struct input_handle {

	void *private;                     //      

	int open;                          //open  
	const char *name;                  //  

	struct input_dev *dev;             //    
	struct input_handler *handler;     //  driver     

	struct list_head	d_node;    //     
	struct list_head	h_node;    //handle   
};

2. 관련 조작 함수
1. 핵심 파일 input. c, input 서브 시스템 초기 화 에 관심 을 가 져 라.
static int __init input_init(void)
{
	int err;

	err = class_register(&input_class);                          //  input ,   sys/class        
	if (err) {
		pr_err("unable to register input_dev class
"); return err; } err = input_proc_init(); // proc (bus/input) if (err) goto fail1; err = register_chrdev(INPUT_MAJOR, "input", &input_fops); // , 13 if (err) { pr_err("unable to register char major %d", INPUT_MAJOR); goto fail2; } return 0; fail2: input_proc_exit(); fail1: class_unregister(&input_class); return err; }
뚝 그 친 것 같은 데, ^. ^!,
2. input 서브 시스템 에 장치 의 함 수 를 추가 합 니 다.
int input_register_device(struct input_dev *dev)
{
	static atomic_t input_no = ATOMIC_INIT(0);
	struct input_handler *handler;
	const char *path;
	int error;

	/* Every input device generates EV_SYN/SYN_REPORT events. */
	__set_bit(EV_SYN, dev->evbit);

	/* KEY_RESERVED is not supposed to be transmitted to userspace. */
	__clear_bit(KEY_RESERVED, dev->keybit);

	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
	input_cleanse_bitmasks(dev);

	if (!dev->hint_events_per_packet)
		dev->hint_events_per_packet =
				input_estimate_events_per_packet(dev);

	/*
	 * If delay and period are pre-set by the driver, then autorepeating
	 * is handled by the driver itself and we don't do it in input.c.
	 */
	init_timer(&dev->timer);
	if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
		dev->timer.data = (long) dev;
		dev->timer.function = input_repeat_key;
		dev->rep[REP_DELAY] = 250;
		dev->rep[REP_PERIOD] = 33;
	}

	if (!dev->getkeycode)
		dev->getkeycode = input_default_getkeycode;                //      ,      

	if (!dev->setkeycode)
		dev->setkeycode = input_default_setkeycode;

	dev_set_name(&dev->dev, "input%ld",                               //name
		     (unsigned long) atomic_inc_return(&input_no) - 1);

	error = device_add(&dev->dev);                                   //       ,  ,,    , bus    ??
	if (error)                                                       //              
		return error;

	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	pr_info("%s as %s
", dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); error = mutex_lock_interruptible(&input_mutex); if (error) { device_del(&dev->dev); return error; } list_add_tail(&dev->node, &input_dev_list); // input device list_for_each_entry(handler, &input_handler_list, node) // handler , handler input_attach_handler(dev, handler); input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); return 0; }
계속해서 inputattach_handler 함수,
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
	const struct input_device_id *id;
	int error;

	id = input_match_device(handler, dev);                                  //       
	if (!id)
		return -ENODEV;

	error = handler->connect(handler, dev, id);                              //     connect  
	if (error && error != -ENODEV)
		pr_err("failed to attach handler %s to device %s, error: %d
", handler->name, kobject_name(&dev->dev.kobj), error); return error; }
함수 도 있어 요.
static const struct input_device_id *input_match_device(struct input_handler *handler,
							struct input_dev *dev)
{
	const struct input_device_id *id;
	int i;

	for (id = handler->id_table; id->flags || id->driver_info; id++) {

		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
			if (id->bustype != dev->id.bustype)
				continue;

		if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
			if (id->vendor != dev->id.vendor)
				continue;

		if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
			if (id->product != dev->id.product)
				continue;

		if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
			if (id->version != dev->id.version)
				continue;

		MATCH_BIT(evbit,  EV_MAX);
		MATCH_BIT(keybit, KEY_MAX);
		MATCH_BIT(relbit, REL_MAX);
		MATCH_BIT(absbit, ABS_MAX);
		MATCH_BIT(mscbit, MSC_MAX);
		MATCH_BIT(ledbit, LED_MAX);
		MATCH_BIT(sndbit, SND_MAX);
		MATCH_BIT(ffbit,  FF_MAX);
		MATCH_BIT(swbit,  SW_MAX);

		if (!handler->match || handler->match(handler, dev))             //     match  ,         ,  
			return id;                                               //        
	}

	return NULL;
}

3. handler 의 등록
같은 handler 도 등록 해 야 돼 요.
int input_register_handler(struct input_handler *handler)
{
	struct input_dev *dev;
	int retval;

	retval = mutex_lock_interruptible(&input_mutex);
	if (retval)
		return retval;

	INIT_LIST_HEAD(&handler->h_list);

	if (handler->fops != NULL) {
		if (input_table[handler->minor >> 5]) {
			retval = -EBUSY;
			goto out;
		}
		input_table[handler->minor >> 5] = handler;
	}

	list_add_tail(&handler->node, &input_handler_list);         //    handler  

	list_for_each_entry(dev, &input_dev_list, node)            //  devices  ,  
		input_attach_handler(dev, handler);

	input_wakeup_procfs_readers();

 out:
	mutex_unlock(&input_mutex);
	return retval;
}

3. input deivce 인 스 턴 스
이 물건 은 그래도 예 를 찾 는 것 이 비교적 편리 해 보인다.
터치 스크린 아래 s3c 2410ts.c,
바로 주제 로 들 어가 서 probe 를 보 세 요.
static int __devinit s3c2410ts_probe(struct platform_device *pdev)
{
	struct s3c2410_ts_mach_info *info;
	struct device *dev = &pdev->dev;
	struct input_dev *input_dev;
	struct resource *res;
	int ret = -EINVAL;

	/* Initialise input stuff */
	memset(&ts, 0, sizeof(struct s3c2410ts));

	ts.dev = dev;

	info = pdev->dev.platform_data;
	if (!info) {
		dev_err(dev, "no platform data, cannot attach
"); return -EINVAL; } dev_dbg(dev, "initialising touchscreen
"); ts.clock = clk_get(dev, "adc"); // clock if (IS_ERR(ts.clock)) { dev_err(dev, "cannot get adc clock source
"); return -ENOENT; } clk_enable(ts.clock); // clock dev_dbg(dev, "got and enabled clocks
"); ts.irq_tc = ret = platform_get_irq(pdev, 0); // if (ret < 0) { dev_err(dev, "no resource for interrupt
"); goto err_clk; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); // if (!res) { dev_err(dev, "no resource for registers
"); ret = -ENOENT; goto err_clk; } ts.io = ioremap(res->start, resource_size(res)); // if (ts.io == NULL) { dev_err(dev, "cannot map registers
"); ret = -ENOMEM; goto err_clk; } /* inititalise the gpio */ if (info->cfg_gpio) info->cfg_gpio(to_platform_device(ts.dev)); // gpio ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, // adc ,select timer adc s3c24xx_ts_conversion, 1); if (IS_ERR(ts.client)) { dev_err(dev, "failed to register adc client
"); ret = PTR_ERR(ts.client); goto err_iomap; } /* Initialise registers */ if ((info->delay & 0xffff) > 0) writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); input_dev = input_allocate_device(); // , input device if (!input_dev) { dev_err(dev, "Unable to allocate the input device !!
"); ret = -ENOMEM; goto err_iomap; } ts.input = input_dev; ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0); ts.input->name = "S3C24XX TouchScreen"; ts.input->id.bustype = BUS_HOST; ts.input->id.vendor = 0xDEAD; ts.input->id.product = 0xBEEF; ts.input->id.version = 0x0102; ts.shift = info->oversampling_shift; ts.features = platform_get_device_id(pdev)->driver_data; ret = request_irq(ts.irq_tc, stylus_irq, 0, // ,input ,pen down up "s3c2410_ts_pen", ts.input); if (ret) { dev_err(dev, "cannot get TC interrupt
"); goto err_inputdev; } dev_info(dev, "driver attached, registering input device
"); /* All went ok, so register to the input system */ ret = input_register_device(ts.input); // input device if (ret < 0) { dev_err(dev, "failed to register input device
"); ret = -EIO; goto err_tcirq; } return 0; err_tcirq: free_irq(ts.irq_tc, ts.input); err_inputdev: input_free_device(ts.input); err_iomap: iounmap(ts.io); err_clk: del_timer_sync(&touch_timer); clk_put(ts.clock); return ret; }
    input_allocate_device  ,

struct input_dev *input_allocate_device(void)
{
	struct input_dev *dev;

	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
	if (dev) {
		dev->dev.type = &input_dev_type;        //    input  
		dev->dev.class = &input_class; 
		device_initialize(&dev->dev);
		mutex_init(&dev->mutex);
		spin_lock_init(&dev->event_lock);
		INIT_LIST_HEAD(&dev->h_list);
		INIT_LIST_HEAD(&dev->node);

		__module_get(THIS_MODULE);
	}

	return dev;
}
irq 는 pen down up 을 판단 하고 adc 를 시작 하여 좌표 사건 을 보고 합 니 다.
미 완성 계속...
Thanks

좋은 웹페이지 즐겨찾기