2014-01-11 7 views
1

1, 2 또는 3이어야하는 3, 2, 1 또는 없음 숫자 조합을 수신하여 키보드 led를 켜고 끄는 장치 드라이버를 만들고 있습니다. 를 걸 경우 :inb() 및 outb()를 사용하여 포트에 액세스하는 드라이버

echo 12 > /dev/ledDevice 

Num Lock 표시에 설정해야이 프로그램은, 잠금 캡 내가 작성하는 경우, 스크롤 잠금을 해제 :

echo "" > /dev/ledDevice 

모든 꺼져, 또는 경우에 설정해야 주도 echo 123이 될 것입니다. 그러나 이런 일은 일어나지 않으며 항상 꺼져 있습니다. 그들은 1, 또한 2, O 위치에, 정수로 표현 포트에서 (데비안 6) ubicated되지만 나는 그것이 관련이있는 경우, 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; 
} 
+2

IIRC와 같은 프로그램은 이미 존재합니다 :'setleds'와'xkbvleds'; 그래서 그들의 소스 코드를 연구하십시오 (아마 커널 코드가 필요 없습니다). –

+0

Esa UCM !! Prueba haciendo una xor en vez de una 또는. El^{^ – Jesus

+0

나는 이미 그것을 해결했다. (예, UCM) 문제는 체인 길이가 아닌 바이트 수로 이루어진 사용자의 복사본과 관련이 있으므로 strlen()을 사용해야한다. 포트에 직접 액세스하는 경우 ACK가 정상적인 경고입니다. – Kaostias

답변

2

이것은 많은 상황에서 트리거 될 수 있습니다. 상당수의 주요 스위처 및 기타 도구가 ATKBD_RET_NAK을 트리거하며 일부 경우에는 확실히 도움이되지 않습니다.

코드가 단순한 것으로 간주하여 오류 코드를 제거해 보겠습니다. 그것의 모양에서, 오류는 atkbd_interrupt 호출에서 발생하는 것 같습니다.

atkbd_interrupt()은 키보드에서 이벤트로 수신 한 데이터를 처리합니다.

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

특정 오류 메시지 인해 unsigned char data 인자에 결합하는 경우 ATKBD_RET_NAK 트리거링 발생한다.

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을 우회 해보십시오.