[C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

[C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by kubawal »

Hi!

My problem is like that: I'm writing my first OS and currently i'm writing keyboard driver. It works properly, but when I turn scancodes into ASCII codes using scancode set 2, it was wrong. E.g when I type

Code: Select all

asdfghjkl[Enter]
it displays

Code: Select all

~~cxde43~w
(~ is key that is not defined in set 2). My function:

Code: Select all

char mosKbdToASCII( Key k, unsigned st ) // st - keyboard state bit enum
{
    const int maxKeynum = 0x66; // max implemented key
    if( st &( unsigned ) KbdState::Shift )
    {
        // with shift
        static char shiftMp[ maxKeynum + 1 ] =
        {
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, '\t', '~', 0, 0, 0, 0, 0,
            'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@',
            0, 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0,
            ' ', 'V', 'F', 'T', 'R', '%', 0, 0, 'N',
            'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J',
            'U', '&', '*', 0, 0, '<', 'K', 'I', 'O', ')',
            '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0,
            0, 0, '\"', 0, '{', '+', 0, 0, 0, 0,
            '\n', '}', 0, '|', 0, 0, 0, 0, '\b'
        };
        if(( int ) k > maxKeynum + 1 )
             return 0;
        else
             return shiftMp[( int ) k ];
        
    }
    
    // normal   
    static char mp[ maxKeynum + 1 ] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, '\t', '`', 0, 0, 0, 0, 0,
        'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2',
        0, 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0,
        ' ', 'v', 'f', 't', 'r', '5', 0, 0, 'n',
        'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j',
        'u', '7', '8', 0, 0, ',', 'k', 'i', 'o', '0',
        '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0,
        0, 0, '\'', 0, '[', '=', 0, 0, 0, 0,
        '\n', ']', 0, '\\', 0, 0, 0, 0, '\b',
    };
    
    
    
    if(( int ) k > maxKeynum + 1 )
         return 0;
    else
         return mp[( int ) k ];
    
}

// funcs to reading keys
Key mosReadKey()
{
    // mosReadKbd() gets key form keyboard without timeout
    // kbdBuf is simple queue
    if( kbdBuf.empty() ) // buffer is empty
    {
        Key k = mosReadKbd(); // mosReadKbd() wait until is any key is pressed and returns it
        while( !processKey( k ) || k == Key::None ) // processKey() support 'break' codes and keyboard states (e.g shift pressed), returns true if key can be gived to user
             k = mosReadKbd();
        
        return k;
    }
    else
         return kbdBuf.pop();
    
}

char mosReadChar() // simply read key and translate it into ASCII
{
    Key k = mosReadKey();
    return mosKbdToASCII( k, kbdSt );
}
And I've got second problem: when I trying to enable keyboard IRQ1, it doesn't call.

Code: Select all

// add record to IDT
#define _set_gate(gate_addr,type,dpl,addr) \
      __asm__ __volatile__("movw %%dx,%%ax\n\t" \
            "movw %0,%%dx\n\t" \
            "movl %%eax,%1\n\t" \
            "movl %%edx,%2\n\t" \
            : :"i"((short)(0x8000+(dpl<<13)+(type<<8))), \
              "o"(*((char *)(gate_addr))), \
              "o"(*(4+(char *)(gate_addr))), \
              "d"((char *)(addr)),"a"(0x00080000)) \
 	

void mosSetIntGate( int n, void * p ) // register interrupt
{
    _set_gate( & mosIDT[ n ], 14, 0, p );
}

// enable IRQ
void mosEnableIRQ( unsigned int num )
{
    unsigned int mask = ~( 1 << num );
    cached_irq_mask &= mask;
    if( irq & 8 ) {
        mosWritePort( cached_A1, 0xA1 );
    } else {
        mosWritePort( cached_21, 0x21 );
    }
}

#define ASMCALL extern "C" // to avoid c++ compiler name conversation


ASMCALL void doIrq1() // keyboard interrupt code
{
    Key k =( Key ) mosReadPort( KBD_DATA_PORT );
    if( processKey( k ) ) kbdBuf.push( k );
}

ASMCALL void irq1(); // asm interrupt function

void mosInitKbd()
{
    kbdSt = 0;
    while( !kbdBuf.empty() ) kbdBuf.pop(); // clear buffer
    
    mosSetIntGate( 0x21,( void * ) irq1 ); // set interrupt to propely address
    mosEnableIRQ( 1 );
}
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by Gigasoft »

You need to set the Controller Configuration Byte. It should be set to 7 to enable both IRQs and disable translation, which is what you probably want.

Code: Select all

_outp(0x64,0x60);
_outp(0x60,7);
By the way, having drivers install IDT entries directly might not be the best of ideas. In a multitasking system, an interrupt handler might wake up a higher priority thread, so you'll need to check for this after every interrupt, and you also need to keep track of whether you are already in an interrupt so you don't switch away from an executing interrupt handler, so there should be some system code that does all this without the involvement of driver code.
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by kubawal »

I tried to this before i create this topic, and it's not working.
When I use this code i've got (for typing

Code: Select all

asdfghjkl
)

Code: Select all

wwaaeettyygguuii;;
(keys doubles)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by Combuster »

keys doubles
That sounds like you're not separating up events from down events.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by kubawal »

i seperate this in mosProcessKey() (it returns true if key is pressed)
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by iansjack »

Are you sure? You don't show us that function so it's not possible to check but iut certainly sounds logical that you are processing both key down and key up events.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by Gigasoft »

Your tables are wrong. The buffer mechanism is also highly suspicious. Implement a proper interrupt safe and blocking queue, and don't use std::queue. It comes as no surprise that data is being read twice or in the wrong order.
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by kubawal »

Gigasoft wrote:and don't use std::queue. It comes as no surprise that data is being read twice or in the wrong order.
I use my implmentation of queue
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by iansjack »

Another potential source of error that we can't really comment on as you haven't shown us the code. As you seem fairly sure that you know where the error doesn't lie perhaps it's time to do some debugging? That way you can narrow down the possibilities. Once you start debugging and gather some evidence it should be fairly simple to see what is causing this sort of error.
kubawal
Member
Member
Posts: 26
Joined: Thu Mar 06, 2014 9:14 am

Re: [C++]Wrong keyboard scancodes (set 2) + IRQ1 didn't call

Post by kubawal »

Now it's OK, I simply use set 1. But it works only for my keyboard...
Post Reply