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

📄 atkbd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
					atkbd->last = 0;					break;				case 1:					atkbd->last = code;					atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;					break;				case 2:					if (!time_after(jiffies, atkbd->time) && atkbd->last == code)						value = 1;					break;			}			atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);	}	if (atkbd->scroll) {		input_regs(atkbd->dev, regs);		if (click != -1)			input_report_key(atkbd->dev, BTN_MIDDLE, click);		input_report_rel(atkbd->dev, REL_WHEEL, scroll);		input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);		input_sync(atkbd->dev);	}	atkbd->release = 0;out:	return IRQ_HANDLED;}/* * atkbd_event_work() is used to complete processing of events that * can not be processed by input_event() which is often called from * interrupt context. */static void atkbd_event_work(void *data){	const short period[32] =		{ 33,  37,  42,  46,  50,  54,  58,  63,  67,  75,  83,  92, 100, 109, 116, 125,		 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };	const short delay[4] =		{ 250, 500, 750, 1000 };	struct atkbd *atkbd = data;	struct input_dev *dev = atkbd->dev;	unsigned char param[2];	int i, j;	down(&atkbd->event_sem);	if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {		param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)			 | (test_bit(LED_NUML,    dev->led) ? 2 : 0)			 | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);		ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);		if (atkbd->extra) {			param[0] = 0;			param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)				 | (test_bit(LED_SLEEP,   dev->led) ? 0x02 : 0)				 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)				 | (test_bit(LED_MISC,    dev->led) ? 0x10 : 0)				 | (test_bit(LED_MUTE,    dev->led) ? 0x20 : 0);			ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);		}	}	if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {		i = j = 0;		while (i < 31 && period[i] < dev->rep[REP_PERIOD])			i++;		while (j < 3 && delay[j] < dev->rep[REP_DELAY])			j++;		dev->rep[REP_PERIOD] = period[i];		dev->rep[REP_DELAY] = delay[j];		param[0] = i | (j << 5);		ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);	}	up(&atkbd->event_sem);}/* * Event callback from the input module. Events that change the state of * the hardware are processed here. If action can not be performed in * interrupt context it is offloaded to atkbd_event_work. */static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){	struct atkbd *atkbd = dev->private;	if (!atkbd->write)		return -1;	switch (type) {		case EV_LED:			set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);			wmb();			schedule_work(&atkbd->event_work);			return 0;		case EV_REP:			if (!atkbd->softrepeat) {				set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);				wmb();				schedule_work(&atkbd->event_work);			}			return 0;	}	return -1;}/* * atkbd_enable() signals that interrupt handler is allowed to * generate input events. */static inline void atkbd_enable(struct atkbd *atkbd){	serio_pause_rx(atkbd->ps2dev.serio);	atkbd->enabled = 1;	serio_continue_rx(atkbd->ps2dev.serio);}/* * atkbd_disable() tells input handler that all incoming data except * for ACKs and command response should be dropped. */static inline void atkbd_disable(struct atkbd *atkbd){	serio_pause_rx(atkbd->ps2dev.serio);	atkbd->enabled = 0;	serio_continue_rx(atkbd->ps2dev.serio);}/* * atkbd_probe() probes for an AT keyboard on a serio port. */static int atkbd_probe(struct atkbd *atkbd){	struct ps2dev *ps2dev = &atkbd->ps2dev;	unsigned char param[2];/* * Some systems, where the bit-twiddling when testing the io-lines of the * controller may confuse the keyboard need a full reset of the keyboard. On * these systems the BIOS also usually doesn't do it for us. */	if (atkbd_reset)		if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))			printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);/* * Then we check the keyboard ID. We should get 0xab83 under normal conditions. * Some keyboards report different values, but the first byte is always 0xab or * 0xac. Some old AT keyboards don't report anything. If a mouse is connected, this * should make sure we don't try to set the LEDs on it. */	param[0] = param[1] = 0xa5;	/* initialize with invalid values */	if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {/* * If the get ID command failed, we check if we can at least set the LEDs on * the keyboard. This should work on every keyboard out there. It also turns * the LEDs off, which we want anyway. */		param[0] = 0;		if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))			return -1;		atkbd->id = 0xabba;		return 0;	}	if (param[0] != 0xab && param[0] != 0xac &&	/* Regular and NCD Sun keyboards */	    param[0] != 0x2b && param[0] != 0x5d &&	/* Trust keyboard, raw and translated */	    param[0] != 0x60 && param[0] != 0x47)	/* NMB SGI keyboard, raw and translated */		return -1;	atkbd->id = (param[0] << 8) | param[1];	if (atkbd->id == 0xaca1 && atkbd->translated) {		printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");		printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");		return -1;	}	return 0;}/* * atkbd_select_set checks if a keyboard has a working Set 3 support, and * sets it into that. Unfortunately there are keyboards that can be switched * to Set 3, but don't work well in that (BTC Multimedia ...) */static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra){	struct ps2dev *ps2dev = &atkbd->ps2dev;	unsigned char param[2];	atkbd->extra = 0;/* * For known special keyboards we can go ahead and set the correct set. * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and * IBM RapidAccess / IBM EzButton / Chicony KBP-8993 keyboards. */	if (atkbd->translated)		return 2;	if (atkbd->id == 0xaca1) {		param[0] = 3;		ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET);		return 3;	}	if (allow_extra) {		param[0] = 0x71;		if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {			atkbd->extra = 1;			return 2;		}	}	if (target_set != 3)		return 2;	if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) {		atkbd->id = param[0] << 8 | param[1];		return 2;	}	param[0] = 3;	if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))		return 2;	param[0] = 0;	if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET))		return 2;	if (param[0] != 3) {		param[0] = 2;		if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))		return 2;	}	ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);	return 3;}static int atkbd_activate(struct atkbd *atkbd){	struct ps2dev *ps2dev = &atkbd->ps2dev;	unsigned char param[1];/* * Set the LEDs to a defined state. */	param[0] = 0;	if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))		return -1;/* * Set autorepeat to fastest possible. */	param[0] = 0;	if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))		return -1;/* * Enable the keyboard to receive keystrokes. */	if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {		printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",			ps2dev->serio->phys);		return -1;	}	return 0;}/* * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a * reboot. */static void atkbd_cleanup(struct serio *serio){	struct atkbd *atkbd = serio_get_drvdata(serio);	ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);}/* * atkbd_disconnect() closes and frees. */static void atkbd_disconnect(struct serio *serio){	struct atkbd *atkbd = serio_get_drvdata(serio);	atkbd_disable(atkbd);	/* make sure we don't have a command in flight */	synchronize_sched();  /* Allow atkbd_interrupt()s to complete. */	flush_scheduled_work();	device_remove_file(&serio->dev, &atkbd_attr_extra);	device_remove_file(&serio->dev, &atkbd_attr_scroll);	device_remove_file(&serio->dev, &atkbd_attr_set);	device_remove_file(&serio->dev, &atkbd_attr_softrepeat);	device_remove_file(&serio->dev, &atkbd_attr_softraw);	input_unregister_device(atkbd->dev);	serio_close(serio);	serio_set_drvdata(serio, NULL);	kfree(atkbd);}/* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set */static void atkbd_set_keycode_table(struct atkbd *atkbd){	int i, j;	memset(atkbd->keycode, 0, sizeof(atkbd->keycode));	if (atkbd->translated) {		for (i = 0; i < 128; i++) {			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];			if (atkbd->scroll)				for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)					if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)						atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;		}	} else if (atkbd->set == 3) {		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));	} else {		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));		if (atkbd->scroll)			for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)				atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;	}}/* * atkbd_set_device_attrs() sets up keyboard's input device structure */static void atkbd_set_device_attrs(struct atkbd *atkbd){	struct input_dev *input_dev = atkbd->dev;	int i;	if (atkbd->extra)		sprintf(atkbd->name, "AT Set 2 Extra keyboard");	else		sprintf(atkbd->name, "AT %s Set %d keyboard",			atkbd->translated ? "Translated" : "Raw", atkbd->set);	sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);	input_dev->name = atkbd->name;	input_dev->phys = atkbd->phys;	input_dev->id.bustype = BUS_I8042;	input_dev->id.vendor = 0x0001;	input_dev->id.product = atkbd->translated ? 1 : atkbd->set;	input_dev->id.version = atkbd->id;	input_dev->event = atkbd_event;	input_dev->private = atkbd;	input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);	if (atkbd->write) {		input_dev->evbit[0] |= BIT(EV_LED);		input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);	}	if (atkbd->extra)		input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |					BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);	if (!atkbd->softrepeat) {

⌨️ 快捷键说明

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