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

📄 ps2_kbd_mouse.c

📁 iic总线控制led,我就这是根据linux下面的驱动自己改的
💻 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_t
read_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 + -