使用inb()和outb()访问端口的驱动程序

时间:2014-01-11 11:49:33

标签: c linux keyboard linux-device-driver hardware-port

我正在制作一个设备驱动程序,通过接收三个,两个,一个或任何数字的组合来打开和关闭键盘LED,如果我做的话,应该是1,2或3:

 echo 12 > /dev/ledDevice

如果我写了:

,程序应该打开Num lock,Caps lock并关闭滚动锁定
 echo "" > /dev/ledDevice

每个LED应该关闭,或者如果它是echo 123则打开但是这不会发生,它们总是关闭。它们在一个用整数表示的端口中,在位置o,1和2中被ubicated(在debian 6中)。另外但我不知道它是否相关,outb在系统日志中产生这个退出

atkbd.c: Spurious ACK on isa0060/serio0. Some program might be trying access hardware directly.

这是我的来源

static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
    char aux[BUF_LEN];
    int state = 0x00;
    int stateInitial = 0x00;
    int i =0;

    int timeout = 0;
    int retries = 7;
    printk(KERN_ALERT "Entering device_write");

    if(copy_from_user(aux,buff,len)){
        printk(KERN_ALERT "Problems in copy from user");
        return -EINVAL;
    }
    if (len  <= 4){
        for (i=0; i<len;i++){
            if(aux[i] == '3'){
                state = state | 0x01; //Scroll lock
            }else if(aux[i] == '1'){
                state = state | 0x02; //Caps lock
            }else if(aux[i]== '2'){
                state= state | 0x04; //Num lock
            }else if (aux[i] != '\n'){
                printk(KERN_ALERT "Error, wrong input.");
                return -EINVAL;
            }
        }
    }else   return -EINVAL;

    if (down_interruptible(&mtx)) /*SEMAPHORE LOCK*/
        return -EINTR;

    stateInitial = inb(0xed);

    stateInitial = stateInitial & 0xF8; //248 mask that deletes the 1, 2 and 3 bits (the led ones)
    state = stateInitial | state;

    /*
     Aquí se modifican los leds
    */
    timeout = 1000;
    outb(0xed,0x60); // Telling the keyboard that we want to modify the leds
    udelay(timeout);

    while (retries!=0 && inb(0x60)!=0xfa) { // Waiting for the controller
        retries--;
        udelay(timeout);
    }
    if (retries!=0) { // prooving the keyboard is ready

        outb(state,0x60);
    }else{  
        up(&mtx);  
        return -EINVAL;
    }
    up(&mtx);

    printk(KERN_ALERT "getting out from device_write, %d bytes read",len);

    return len;
}

1 个答案:

答案 0 :(得分:2)

这可以在无数种情况下触发。相当多的键切换器和其他工具会触发ATKBD_RET_NAK,在某些情况下我们肯定会无能为力。

考虑到您的代码是公正的,让我们尝试打破错误代码。从它的外观来看,错误似乎来自atkbd_interrupt调用。

atkbd_interrupt()处理从键盘接收到的事件数据。

static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char
data, unsigned int flags)
{----}

由于触发与ATKBD_RET_NAK参数耦合的案例unsigned char data而发生特定错误消息。

case ATKBD_RET_NAK:
    if (printk_ratelimit())
        dev_warn(&serio->dev,
             "Spurious %s on %s. "
             "Some program might be trying access hardware directly.\n",
             data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);

atkbd提供对连接到AT键盘控制器的AT增强型键盘的访问。尝试绕过KVM。