링크 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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
용감한 바로 가기 및 우분투 응용 프로그램안녕하세요 여러분, 이 기사에서는 모든 사이트에서 pwa를 생성하고 실행기 응용 프로그램으로 추가하는 방법을 설명하고 싶습니다. 일부 웹사이트는 PWA로 설치를 허용하지 않지만 유사한 애플리케이션을 원합니다. 1. ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.