📄 ps2_kbd_mouse.c
字号:
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 + -