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

📄 ps2_kbd_mouse.c

📁 linux下S3C2410的I2C总线的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		do{			ack=0;			mega8_PS20_Send(data);			mega8_PS20_WaitData(&ack, KBD_TIMEOUT);			if(KBD_REPLY_RESEND==ack){				sleep(HZ/5);				continue;			}			if(KBD_REPLY_ACK==ack)				break;		}while(retries-->0);				PS20_CLR_WAITING();	}	else if(ps2n==1){	//for ps2-1		PS21_SET_WAITING();		do{			ack=0;			mega8_PS21_Send(data);			mega8_PS21_WaitData(&ack, KBD_TIMEOUT);			if(KBD_REPLY_RESEND==ack){				sleep(HZ/5);				continue;			}			if(KBD_REPLY_ACK==ack)				break;		}while(retries-->0);				PS21_CLR_WAITING();	}	spin_unlock_irqrestore(&ps_controller_lock[ps2n], flags);	if(retries==-1){		printk("ps/2 port=%d send failed!, ack=0x%x, data=0x%x\n", ps2n, ack,data);		return -1;	}	sleep(HZ/5);	return 0;}typedef struct{	wait_queue_head_t wait;	unsigned char data;	int exit;}KbdLedCtrl;static KbdLedCtrl ledctrl;static inline void Ps2_Set_KeyboardLed(int ps2n, unsigned char led){	PS2DPRINTK("begin set led done\n");	if ((send_data(ps2n, KBD_CMD_SET_LEDS)<0 || send_data(ps2n, led)<0)) {		PS2DPRINTK("Set led failed!\n");		send_data(ps2n, KBD_CMD_ENABLE);	/* re-enable kbd if any errors */	}	PS2DPRINTK("Set led done\n");}static int Ps2_Kbdled_sendthread(void* ps2n){	init_waitqueue_head(&ledctrl.wait);	ledctrl.exit=0;	for(;;){		interruptible_sleep_on(&ledctrl.wait);		if(ledctrl.exit==1){ //stop this thread			PS2DPRINTK("Ps2_Kbdled_sendthread release!\n");			return 0;		}		sleep(HZ/5);		Ps2_Set_KeyboardLed((int)ps2n, ledctrl.data);	}	return 0;}static void  Ps2_Kbd_leds(unsigned char leds){	PS2DPRINTK("Set led = 0x%x\n", leds);	ledctrl.data=leds;	wake_up_interruptible(&ledctrl.wait);}static ps2_handle_event  __init Ps2_kbd_init_hw(int ps2n){	int i;	static int once=0;	if(once){		printk("I2c-PS/2: can't support two keyboard\n");		return NULL;	}	once++;	//initialization keyboard map	memset(Sc2_Sc1_Map, 0, sizeof(Sc2_Sc1_Map));	memset(Sc2_Sc1_MapE0, 0, sizeof(Sc2_Sc1_MapE0));	for(i=0; i<sizeof(Make_Sc2Sc1_Map)/sizeof(*Make_Sc2Sc1_Map); i++){		Sc2_Sc1_Map[Make_Sc2Sc1_Map[i].Scancode2]=Make_Sc2Sc1_Map[i].Scancode1;	}	for(i=0; i<sizeof(Make_Sc2Sc1_MapE0)/sizeof(*Make_Sc2Sc1_MapE0); i++){		Sc2_Sc1_MapE0[Make_Sc2Sc1_MapE0[i].Scancode2]=Make_Sc2Sc1_MapE0[i].Scancode1;	}	kernel_thread(Ps2_Kbdled_sendthread, (void*)ps2n, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);	k_setkeycode	=  Ps2_Kbd_setkeycode;	k_getkeycode	=  Ps2_Kbd_getkeycode;	k_translate	=  Ps2_Kbd_translate;	k_unexpected_up	=  Ps2_Kbd_unexpected_up;	k_leds		=  Ps2_Kbd_leds;#ifdef CONFIG_MAGIC_SYSRQ	k_sysrq_xlate	=  Ps2_Kbd_sysrq_xlate;	k_sysrq_key	= 0x54;#endif	//sync keyboard led	Ps2_Set_KeyboardLed(ps2n, getledstate());		return handle_PS2kbd_event;}static void Ps2_kbd_release(void){	ledctrl.exit=1;	wake_up_interruptible(&ledctrl.wait);	sleep(HZ/2);}//////////////////////////////////PS/2 mouse//////////////////////////////////* *	PS/2 Auxiliary Device */static int __init psaux_init(void);#define AUX_RECONNECT1 0xaa	/* scancode1 when ps2 device is plugged (back) in */#define AUX_RECONNECT2 0x00	/* scancode2 when ps2 device is plugged (back) in */ static struct aux_queue *queue;	/* Mouse data buffer. */static int aux_count;static int ps2port;#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)#define MAX_RETRIES	60		/* some aux operations take long time*/static inline void handle_mouse_event(int ps2n, unsigned char scancode){	add_mouse_randomness((__u32)scancode);	if (aux_count) {		int head = queue->head;		queue->buf[head] = scancode;		head = (head + 1) & (AUX_BUF_SIZE - 1);		if (head != queue->tail) {			queue->head = head;			if (queue->fasync)				kill_fasync(&queue->fasync, SIGIO, POLL_IN);			wake_up_interruptible(&queue->proc_list);		}	}}static inline void handle_PS2mouse_event(int ps2n, unsigned char data){	handle_mouse_event(ps2n, data);}/* * Send a byte to the mouse. */static void aux_write_dev(int ps2n, int val){	unsigned long flags;	DPRINTK("aux write: val=0x%x",val);	spin_lock_irqsave(&ps_controller_lock[ps2n], flags);	if(ps2n==0)		mega8_PS20_Send(val);	else if(ps2n==1)	//for ps2-1		mega8_PS21_Send(val);	sleep(HZ/5);	spin_unlock_irqrestore(&ps_controller_lock[ps2n], flags);}/* * Send a byte to the mouse & handle returned ack */static void aux_write_ack(int ps2n, unsigned char val){	unsigned char data;	unsigned long flags;	spin_lock_irqsave(&ps_controller_lock[ps2n], flags);	if(ps2n==0){			PS20_SET_WAITING();		mega8_PS20_Send(val);		mega8_PS20_WaitData(&data, MOUSE_TIMEOUT);		PS20_CLR_WAITING();	}	else if(ps2n==1){	//for ps2-1		PS21_SET_WAITING();		mega8_PS21_Send(val);		mega8_PS21_WaitData(&data, MOUSE_TIMEOUT);		PS21_CLR_WAITING();	}	spin_unlock_irqrestore(&ps_controller_lock[ps2n], flags);}static unsigned char get_from_queue(int ps2n){	unsigned char result;	unsigned long flags;	spin_lock_irqsave(&ps_controller_lock[ps2n], flags);	result = queue->buf[queue->tail];	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);	spin_unlock_irqrestore(&ps_controller_lock[ps2n], flags);	return result;}static inline int queue_empty(void){	return queue->head == queue->tail;}static int fasync_aux(int fd, struct file *filp, int on){	int retval;	retval = fasync_helper(fd, filp, on, &queue->fasync);	if (retval < 0)		return retval;	return 0;}/* * Random magic cookie for the aux device */#define AUX_DEV ((void *)queue)static int release_aux(struct inode *inode, struct file *file){	fasync_aux(-1, file, 0);	if (--aux_count)		return 0;	aux_write_ack(ps2port, AUX_DISABLE_DEV);	/* Disable aux device */	if(ps2port==0)		mega8_device_release (DTYPE_PS2_0);	//release ps2	else if(ps2port==1)		mega8_device_release (DTYPE_PS2_1);	//release ps2	return 0;}/* * Install interrupt handler. * Enable auxiliary device. */static int open_aux(struct inode *inode, struct file *file){	if (aux_count++) {		return 0;	}	queue->head = queue->tail = 0;	/* Flush input queue */	if(ps2port==0)		mega8_device_request(DTYPE_PS2_0);	//release ps2	else if(ps2port==1)		mega8_device_request(DTYPE_PS2_1);	//release ps2	/* Enable the   auxiliary port on   controller. */	aux_write_ack(ps2port, AUX_ENABLE_DEV);	/* Enable aux device */	return 0;}/* * Put bytes from input queue to buffer. */static ssize_tread_aux(struct file *file, char *buffer, size_t count, loff_t * ppos){	DECLARE_WAITQUEUE(wait, current);	ssize_t i = count;	unsigned char c;	if (queue_empty()) {		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		add_wait_queue(&queue->proc_list, &wait);	      repeat:		set_current_state(TASK_INTERRUPTIBLE);		if (queue_empty() && !signal_pending(current)) {			schedule();			goto repeat;		}		current->state = TASK_RUNNING;		remove_wait_queue(&queue->proc_list, &wait);	}	while (i > 0 && !queue_empty()) {		c = get_from_queue(ps2port);		put_user(c, buffer++);		i--;	}	if (count - i) {		file->f_dentry->d_inode->i_atime = CURRENT_TIME;		return count - i;	}	if (signal_pending(current))		return -ERESTARTSYS;	return 0;}// Write to the aux device.static ssize_t write_aux(struct file *file, const char *buffer, size_t count, loff_t * ppos){	ssize_t retval = 0;	if (count) {		ssize_t written = 0;		if (count > 32)			count = 32;	/* Limit to 32 bytes. */		do {			char c;			get_user(c, buffer++);			aux_write_dev(ps2port, c);			written++;		}		while (--count);		retval = -EIO;		if (written) {			retval = written;			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;		}	}	return retval;}static unsigned int aux_poll(struct file *file, poll_table * wait){	poll_wait(file, &queue->proc_list, wait);	if (!queue_empty())		return POLLIN | POLLRDNORM;	return 0;}struct file_operations psaux_fops = {	read:		read_aux,	write:		write_aux,	poll:		aux_poll,	open:		open_aux,	release:	release_aux,	fasync:		fasync_aux,};//Initialize driver.static struct miscdevice psaux_mouse = {	PSMOUSE_MINOR, "psaux", &psaux_fops,};static int __init psaux_init(void){	aux_count=0;		misc_register(&psaux_mouse);	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);	memset(queue, 0, sizeof(*queue));	queue->head = queue->tail = 0;	init_waitqueue_head(&queue->proc_list);	aux_write_ack(ps2port, AUX_SET_SAMPLE);	aux_write_ack(ps2port, 50);	/* 100 samples/sec */	aux_write_ack(ps2port, AUX_SET_RES);	aux_write_ack(ps2port, 3);	/* 8 counts per mm */	aux_write_ack(ps2port, AUX_SET_SCALE11);	/* 2:1 scaling */	return 0;}static ps2_handle_event  __init Ps2_Mouse_init_hw(int ps2n){	static int once=0;	if(once){		printk("I2c-PS/2: can't support two Mouse\n");		return NULL;	}	once++;	ps2port=ps2n;	psaux_init();	if(ps2n==0)		mega8_device_release (DTYPE_PS2_0);	//open port when open mouse device	else if(ps2n==1)		mega8_device_release (DTYPE_PS2_1);	//open port when open mouse device	else return NULL;	return handle_PS2mouse_event;}////////////////////////////////for PS/2 port0 ///////////////////////////////////////////////////////////////////for PS/2 port0 end////////////////////////////////

⌨️ 快捷键说明

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