⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mb9260_kbd.c

📁 一个总线扩展的嵌入式Linux键盘驱动程序。
💻 C
字号:
/* *  Keyboard driver for moblle9260. * *  Copyright (c) 2008 liulf, liulf@ihep.ac.cn *  Based on aaed2000_kbd.c. * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation. * */#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/init.h>#include <linux/input-polldev.h>#include <linux/interrupt.h>#include <linux/jiffies.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/wfos_debug.h>#include <linux/wfos_iomem.h>#include <mach/hardware.h>#define NR_SCANCODES		(128)#define SCAN_INTERVAL		(50) /* ms */#define KEYBOARD_PHY_BASE0		0x30000040      /* key1 ~ key16 */#define KEYBOARD_PHY_BASE1		0x30000060      /* key17 ~ key32 */#if 0static unsigned char KEY0_MAP[1] = {	KEY_0,};static unsigned char KEY1_MAP[1] = {	KEY_1,};static unsigned char KEY2_MAP[4] = {	KEY_2, KEY_A, KEY_B, KEY_C,};static unsigned char KEY3_MAP[4] = {	KEY_3, KEY_D, KEY_E, KEY_F,};static unsigned char KEY4_MAP[4] = {	KEY_4, KEY_G, KEY_H, KEY_I,};static unsigned char KEY5_MAP[4] = {	KEY_5, KEY_J, KEY_K, KEY_L,};static unsigned char KEY6_MAP[4] = {	KEY_6, KEY_M, KEY_N, KEY_O,};static unsigned char KEY7_MAP[5] = {	KEY_7, KEY_P, KEY_Q, KEY_R, KEY_S,};static unsigned char KEY8_MAP[4] = {	KEY_8, KEY_T, KEY_U, KEY_V,};static unsigned char KEY9_MAP[5] = {	KEY_W, KEY_X, KEY_Y, KEY_Z,};#endifenum KEY_IDX {	IDX_FUNC = 0,	IDX_BACK,	IDX_UP,	IDX_FN,	IDX_ENTER,	IDX_DEL,	IDX_LEFT,	IDX_ENTER2,	IDX_RIGHT,	IDX_PLUS,	IDX_DOWN,	IDX_STAR,      /* * */	IDX_3DEF,       /* 3/D/E/F */	IDX_2ABC,       /* 2/A/B/C */	IDX_1,          /* 1 */	IDX_0,          /* 0 */	IDX_POUND,      /* # */	IDX_6MNO,       /* 6/M/N/O */	IDX_9WXYZ,      /* 9/W/X/Y/Z */	IDX_5JKL,       /* 5/J/K/L */	IDX_8TUV,       /* 8/T/U/V */	IDX_4GHI,       /* 8/G/H/I */	IDX_7PQRS,      /* 7/P/Q/R/S */};static unsigned int mb9260kbd_keycode[NR_SCANCODES] = {	[IDX_FUNC] = KEY_MENU,	[IDX_BACK] = KEY_BACK,	[IDX_UP] = KEY_UP,	[IDX_FN] = KEY_FN,	[IDX_ENTER] = KEY_ENTER,	[IDX_DEL] = KEY_DELETE,	[IDX_LEFT] = KEY_LEFT,	/* FIX ME! */	[IDX_ENTER2] = KEY_BACK,	[IDX_RIGHT] = KEY_RIGHT,	[IDX_PLUS] = KEY_KPPLUS,	[IDX_DOWN] = KEY_DOWN,	/* comobo key */	[IDX_STAR] = 0,	[IDX_3DEF] = KEY_3,	[IDX_2ABC] = KEY_2,	[IDX_1] = KEY_1,	[IDX_0] = KEY_0,	/* comobo key */	[IDX_POUND] = 0,	[IDX_6MNO] = KEY_6,	[IDX_9WXYZ] = KEY_9,	[IDX_5JKL] = KEY_5,	[IDX_8TUV] = KEY_8,	[IDX_4GHI] = KEY_4,	[IDX_7PQRS] = KEY_7,};struct mb9260kbd {	unsigned char keycode[ARRAY_SIZE(mb9260kbd_keycode)];	struct input_polled_dev *poll_dev;	struct iomem_object *iomem0;		  	struct iomem_object *iomem1;		  	unsigned long key_ever_pressed;	unsigned long kbdscan_state;	unsigned int kbdscan_count[32];};#define KBDSCAN_STABLE_COUNT 2static inline u32 mb9260kbd_getkey(struct mb9260kbd *dev){	u16 key0 = 0xffff, key1 = 0xffff;	struct iomem_object *iomem0 = dev->iomem0;		  	struct iomem_object *iomem1 = dev->iomem1;		iomem0->read_word(iomem0, &key0, IO_RDONLY);	iomem1->read_word(iomem1, &key1, IO_RDONLY);	key1 |= 0xff00; 	return (key0 | (key1 << 16));}static void mb9260kbd_report_key(struct mb9260kbd *mb9260kbd, unsigned long key_stat, unsigned int idx){	unsigned int pressed;	if (unlikely(idx >= ARRAY_SIZE(mb9260kbd_keycode))) {		return;	}	pressed = !test_bit(idx, &key_stat);	switch (idx) {		case  IDX_STAR: /* Key *:  SHIFT + 8 */			input_report_key(mb9260kbd->poll_dev->input,					 KEY_LEFTSHIFT, pressed);			input_report_key(mb9260kbd->poll_dev->input,					 KEY_8, pressed);			break;		case  IDX_POUND: /* Key #: SHIFT + 3 */			input_report_key(mb9260kbd->poll_dev->input,					 KEY_LEFTSHIFT, pressed);			input_report_key(mb9260kbd->poll_dev->input,					 KEY_3, pressed);			break;		default:			input_report_key(mb9260kbd->poll_dev->input,					 mb9260kbd->keycode[idx], pressed);			break;	}	return;}/* Scan the hardware keyboard and push any changes up through the input layer */static void mb9260kbd_poll(struct input_polled_dev *dev){	struct mb9260kbd *mb9260kbd = dev->private;	unsigned long key_stat = 0xffffffff;	unsigned long idx = 0;	int sync = 0;	key_stat = mb9260kbd_getkey(mb9260kbd);	if ((mb9260kbd->key_ever_pressed = 0) 		&& (key_stat == 0xffffffff)		&& (mb9260kbd->kbdscan_state == key_stat)) {	        return;    }	for (idx = IDX_FUNC; idx <= IDX_7PQRS; idx++) {		if (test_bit(idx, &key_stat) 				^ test_bit(idx, &mb9260kbd->kbdscan_state)) {			set_bit(idx, &mb9260kbd->key_ever_pressed);			mb9260kbd->kbdscan_count[idx] = 0;			mb9260kbd->kbdscan_state = key_stat;		} else if (++mb9260kbd->kbdscan_count[idx] >= KBDSCAN_STABLE_COUNT) {			if (test_and_clear_bit(idx, &mb9260kbd->key_ever_pressed)) {				mb9260kbd_report_key(mb9260kbd, key_stat, idx);				sync = 1;			}			mb9260kbd->kbdscan_count[idx] = 0;		}	}	if (sync) {		input_sync(dev->input);	}	return;}static int __devinit mb9260kbd_probe(struct platform_device *pdev){	struct mb9260kbd *mb9260kbd;	struct input_polled_dev *poll_dev;	struct input_dev *input_dev;	int i;	int error;	mb9260kbd = kzalloc(sizeof(struct mb9260kbd), GFP_KERNEL);	if (!mb9260kbd) {		error = -ENOMEM;		goto mb9260kbd_malloc_fail;	}	mb9260kbd->kbdscan_state = 0xffffffff;	mb9260kbd->iomem0 = iomem_object_get(KEYBOARD_PHY_BASE0, 0xffffffff);	if (!mb9260kbd->iomem0) {		printk(KERN_ERR "Can NOT remap address 0x%08x\n", KEYBOARD_PHY_BASE0);		error = -1;		goto iomem0_fail;	}	mb9260kbd->iomem1 = iomem_object_get(KEYBOARD_PHY_BASE1, 0xffffffff);	if (!mb9260kbd->iomem1) {		printk(KERN_ERR "Can NOT remap address 0x%08x\n", KEYBOARD_PHY_BASE1);		error = -1;		goto iomem1_fail;	}	poll_dev = input_allocate_polled_device();	if (!mb9260kbd || !poll_dev) {		error = -ENOMEM;		goto fail;	}	platform_set_drvdata(pdev, mb9260kbd);	mb9260kbd->poll_dev = poll_dev;	memcpy(mb9260kbd->keycode, mb9260kbd_keycode, sizeof(mb9260kbd->keycode));	poll_dev->private = mb9260kbd;	poll_dev->poll = mb9260kbd_poll;	poll_dev->poll_interval = SCAN_INTERVAL;	input_dev = poll_dev->input;	input_dev->name = "Mobile9260 Keyboard";	input_dev->phys = "mb9260kbd/input0";	input_dev->id.bustype = BUS_HOST;	input_dev->id.vendor = 0x0001;	input_dev->id.product = 0x0001;	input_dev->id.version = 0x0100;	input_dev->dev.parent = &pdev->dev;	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);	input_dev->keycode = mb9260kbd->keycode;	input_dev->keycodesize = sizeof(unsigned char);	input_dev->keycodemax = ARRAY_SIZE(mb9260kbd_keycode);	for (i = 0; i < ARRAY_SIZE(mb9260kbd_keycode); i++)		set_bit(mb9260kbd->keycode[i], input_dev->keybit);	clear_bit(0, input_dev->keybit);	error = input_register_polled_device(mb9260kbd->poll_dev);	if (error)		goto fail;	return 0;fail:		input_free_polled_device(poll_dev);	iomem_object_put(mb9260kbd->iomem1);iomem1_fail:	iomem_object_put(mb9260kbd->iomem0);iomem0_fail:	kfree(mb9260kbd);mb9260kbd_malloc_fail:	return error;}static int __devexit mb9260kbd_remove(struct platform_device *pdev){	struct mb9260kbd *mb9260kbd = platform_get_drvdata(pdev);	input_unregister_polled_device(mb9260kbd->poll_dev);	input_free_polled_device(mb9260kbd->poll_dev);	iomem_object_put(mb9260kbd->iomem1);	iomem_object_put(mb9260kbd->iomem0);	kfree(mb9260kbd);	return 0;}/* work with hotplug and coldplug */MODULE_ALIAS("platform:mb9260-keyboard");static struct platform_driver mb9260kbd_driver = {	.probe		= mb9260kbd_probe,	.remove		= __devexit_p(mb9260kbd_remove),	.driver		= {		.name	= "mb9260-kbd",		.owner	= THIS_MODULE,	},};static int __init mb9260kbd_init(void){	return platform_driver_register(&mb9260kbd_driver);}static void __exit mb9260kbd_exit(void){	platform_driver_unregister(&mb9260kbd_driver);}module_init(mb9260kbd_init);module_exit(mb9260kbd_exit);MODULE_AUTHOR("liulf");MODULE_DESCRIPTION("Mobile9260 Keyboard Driver");MODULE_LICENSE("GPL v2");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -