Драйвер получает доступ к портам с помощью inb() и outb()

Я делаю драйвер устройства, который включает и выключает светодиоды клавиатуры, получая любую комбинацию из трех, двух, одной или ни одной цифры, которая должна быть 1, 2 или 3, если я сделаю:

 echo 12 > /dev/ledDevice

Программа должна включить Num Lock, Caps Lock и отключить блокировку прокрутки, если я напишу:

 echo "" > /dev/ledDevice

Каждый светодиод должен быть выключен или включен, если это будет echo 123 но этого не происходит, они всегда выключаются. Они используются (в Debian 6) в порту, представленном целым числом, в позициях o, 1 и 2. Кроме того, но я не знаю, связано ли это, 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 ответ

Это может быть вызвано множеством ситуаций. Многие ключевые переключатели и другие инструменты запускают 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 .

Другие вопросы по тегам