Keyboard PS/2 to main

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
gpsd
Posts: 10
Joined: Tue Oct 22, 2013 6:22 am
Location: Italy

Keyboard PS/2 to main

Post by gpsd »

Hello to all,
I am working with the PS / 2 keyboard. IRQ 1
It works, but I print directly on the character screen, instead of the pressed key to return to the main.
I would use a "return" to the main, which then operates as a key is pressed.
How can I do??

I'll post the code.

thanks

Code: Select all

#include <system.h>
#include <keymap.h>

#define LSHIFT   0x01
#define RSHIFT   0x02
#define LCTRL    0x04
#define RCTRL    0x08
#define ALT      0x10
#define ALTGR    0x20
#define CAPS     0x40
#define CAPSDOWN 0x80

#define SCRLED   0x01
#define NUMLED   0x02
#define CAPSLED  0x04

#define KBD_ACK  0xFA

typedef void (*fptr)(int);

unsigned char kmode   = 0;
unsigned char ke0     = 0;
unsigned char kleds   = NUMLED;
unsigned char kapplic = 0;

static fptr key_table[];

static unsigned char old_leds = NUMLED;
static int npadch = 0;

static void applkey(int key);

/*
 * the keyboard interrupt handler. Here it prints a simple "Hello" message.
 */
void keyboard_interrupt(void) {
	unsigned char scancode, x;

    scancode=inportb(0x60);
    x=inportb(0x61);
    outportb(x|0x80, 0x61);
    outportb(x&0x7f, 0x61);
    outportb(0x20, 0x20);

    if (scancode == 0xE0) {
        ke0 = 1;
    } else if (scancode == 0xE1) {
        ke0 = 2;
    } else {		
        return key_table[scancode](scancode);
        ke0 = 0;
    }
}

/*
 * kb_wait waits for the keyboard controller buffer to empty.
 */
static void kb_wait(void) {
    int i;

    for (i=0; i<0x10000; i++) {
        if ((inportb(0x64) & 0x02) == 0) {
            break;
		}
	}
}

void kb_ack(void) {
    int i;

    for(i=0; i<0x10000; i++) {
        if (inportb(0x60) == KBD_ACK) {
            break;
        }
    }
}

static void none(int sc) {
}

static void do_self(int sc) {
	unsigned char ch;

    if (kmode & ALTGR) {
	    ch=alt_map[sc];
    } else if (kmode & (LSHIFT|RSHIFT|LCTRL|RCTRL)) {
        ch=shift_map[sc];
    } else {
        ch=key_map[sc];
    }

	if (ch == 0) {
		return;
	}

    // If CTRL is active the character CTRL-A == 0x01, CTRL-B == 0x02,
    // CTRL-Z == 0x1A.
    if (kmode & (LCTRL|RCTRL|CAPS)) {
        if ((ch>='a' && ch <='z') || (ch>=224 && ch<=254)) {
            ch -= 32;
        }
    }

    if (kmode & (LCTRL|RCTRL)) {
        ch &= 0x1f;
    }

    // If the character has been pressed in combination with
    // ALT key, the bit 7 is activated. For LATIN-1 map the character is
    // prepended with 0x33 value (now not handled).
    if (kmode & ALT) {
        ch |= 0x80;
    }
	
	//putch(ch);  <-- PRINT CHAR TO SCREEN
}

static void enter(int sc) {
    if (ke0 != 1)
        do_self(sc);
    else if (kapplic)
        applkey('M');
    else
        do_self(sc);
}

static void ctrl(int sc) {
    if (ke0) {
        kmode|=RCTRL;
    } else {
        kmode|=LCTRL;
    }
}

static void unctrl(int sc) {
    if (ke0) {
        kmode&=(~RCTRL);
    } else {
        kmode&=(~LCTRL);
    }
}

static void lshift(int sc) {
	kmode|=LSHIFT;
}

static void unlshift(int sc) {
	kmode&=(~LSHIFT);
}

static void slash(int sc) {
    if (ke0 != 1) {
        do_self(sc);
    } else if (kapplic) {
        applkey('Q');
    } else {
		puts("/");
    }
}

static void rshift(int sc) {
    kmode|=RSHIFT;
}

static void unrshift(int sc) {
    kmode&=(~RSHIFT);
}

static void star(int sc) {
    if (kapplic)
        applkey('R');
    else
        do_self(sc);
}

static void alt(int sc) {
    if (ke0) {
        kmode|=ALTGR;
    } else {
        kmode|=ALT;
    }
}

static void unalt(int sc) {
    if (ke0) {
        kmode&=(~ALTGR);
    } else {
        kmode&=(~ALT);

        // check if we press ALT-char code. For example if we press
		// ALT-126 the ~ character should be printed.
		if (npadch != 0) {
			puts(npadch);
		    npadch=0;
		}
    }
}

void set_leds(void) {
    if (kleds != old_leds) {
        old_leds=kleds;
        kb_wait();
        outportb(0xED, 0x60);
        kb_ack();
        kb_wait();
        outportb(kleds, 0x60);
        kb_ack();
    }
}

static void caps(int sc) {
    if (!(kmode&CAPSDOWN)) {
	    kleds^=CAPSLED;
        kmode^=CAPS;
        kmode|=CAPSDOWN;
        set_leds();
    }
}

static void uncaps(int sc) {
	kmode&=(~CAPSDOWN);
}

static void func(int sc) {
    if (sc < 0x3b) {
        return;
    }

    sc-=0x3b;
    if (sc > 9) {
        sc-=18;
        if (sc < 10 || sc > 11)
            return;
    }

    if ((kmode & (LCTRL|RCTRL)) && (kmode & ALT)) {
        //
    } else {
        puts(func_map[sc]);
    }
}

static void num(int sc) {
    if (kapplic)
        applkey(0x50);
    else {
        kleds^=NUMLED;
        set_leds();
    }
}

static void scroll(int sc) {
    kleds^=SCRLED;
    set_leds();
}

static void cursor(int sc) {
    unsigned char ch;

    if (sc < 0x47 || sc > 0x53) {
        return;
	}

	sc-=0x47;

	// if CTRL-ALT-DEL has been pressed
    if (sc == 12 && (kmode&(LCTRL|RCTRL)) && (kmode&(ALT|ALTGR))) {
        //
        return;
    }

    if (ke0 == 1) {
        //cur(sc);
        return;
    }

    // the user is pressing ALT-numpad.
    if ((kmode & ALT) && sc!=12) {
        npadch=npadch*10 + pad_map[sc];
        return;
    }

    if (kleds & NUMLED) {
        ch = num_map[sc];

		puts(ch);
    }
}

static void minus(int sc) {
    if (kapplic) {
        applkey('S');
    } else {
        do_self(sc);
    }
}

static void plus(int sc) {
    if (kapplic)
        applkey('l');
    else
        do_self(sc);
}

long no_idt[2] = {0, 0};

static void applkey(int key) {
    // not implemented here
}

static fptr key_table[] = {
    none,do_self,do_self,do_self,       /* 00-03 s0 esc 1 2 */
    do_self,do_self,do_self,do_self,    /* 04-07 3 4 5 6 */
    do_self,do_self,do_self,do_self,    /* 08-0B 7 8 9 0 */
    do_self,do_self,do_self,do_self,    /* 0C-0F + ' bs tab */
    do_self,do_self,do_self,do_self,    /* 10-13 q w e r */
    do_self,do_self,do_self,do_self,    /* 14-17 t y u i */
    do_self,do_self,do_self,do_self,    /* 18-1B o p } ^ */
    enter,ctrl,do_self,do_self,         /* 1C-1F enter ctrl a s */
    do_self,do_self,do_self,do_self,    /* 20-23 d f g h */
    do_self,do_self,do_self,do_self,    /* 24-27 j k l | */
    do_self,do_self,lshift,do_self,     /* 28-2B { para lshift , */
    do_self,do_self,do_self,do_self,    /* 2C-2F z x c v */
    do_self,do_self,do_self,do_self,    /* 30-33 b n m , */
    do_self,slash,rshift,star,          /* 34-37 . - rshift * */
    alt,do_self,caps,func,              /* 38-3B alt sp caps f1 */
    func,func,func,func,                /* 3C-3F f2 f3 f4 f5 */
    func,func,func,func,                /* 40-43 f6 f7 f8 f9 */
    func,num,scroll,cursor,             /* 44-47 f10 num scr home */
    cursor,cursor,minus,cursor,         /* 48-4B up pgup - left */
    cursor,cursor,plus,cursor,          /* 4C-4F n5 right + end */
    cursor,cursor,cursor,cursor,        /* 50-53 dn pgdn ins del */
    none,none,do_self,func,             /* 54-57 sysreq ? < f11 */
    func,none,none,none,                /* 58-5B f12 ? ? ? */
    none,none,none,none,                /* 5C-5F ? ? ? ? */
    none,none,none,none,                /* 60-63 ? ? ? ? */
    none,none,none,none,                /* 64-67 ? ? ? ? */
    none,none,none,none,                /* 68-6B ? ? ? ? */
    none,none,none,none,                /* 6C-6F ? ? ? ? */
    none,none,none,none,                /* 70-73 ? ? ? ? */
    none,none,none,none,                /* 74-77 ? ? ? ? */
    none,none,none,none,                /* 78-7B ? ? ? ? */
    none,none,none,none,                /* 7C-7F ? ? ? ? */
    none,none,none,none,                /* 80-83 ? br br br */
    none,none,none,none,                /* 84-87 br br br br */
    none,none,none,none,                /* 88-8B br br br br */
    none,none,none,none,                /* 8C-8F br br br br */
    none,none,none,none,                /* 90-93 br br br br */
    none,none,none,none,                /* 94-97 br br br br */
    none,none,none,none,                /* 98-9B br br br br */
    none,unctrl,none,none,              /* 9C-9F br unctrl br br */
    none,none,none,none,                /* A0-A3 br br br br */
    none,none,none,none,                /* A4-A7 br br br br */
    none,none,unlshift,none,            /* A8-AB br br unlshift br */
    none,none,none,none,                /* AC-AF br br br br */
    none,none,none,none,                /* B0-B3 br br br br */
    none,none,unrshift,none,         /* B4-B7 br br unrshift br */
    unalt,none,uncaps,none,             /* B8-BB unalt br uncaps br */
    none,none,none,none,                /* BC-BF br br br br */
    none,none,none,none,                /* C0-C3 br br br br */
    none,none,none,none,                /* C4-C7 br br br br */
    none,none,none,none,                /* C8-CB br br br br */
    none,none,none,none,                /* CC-CF br br br br */
    none,none,none,none,                /* D0-D3 br br br br */
    none,none,none,none,                /* D4-D7 br br br br */
    none,none,none,none,                /* D8-DB br ? ? ? */
    none,none,none,none,                /* DC-DF ? ? ? ? */
    none,none,none,none,                /* E0-E3 e0 e1 ? ? */
    none,none,none,none,                /* E4-E7 ? ? ? ? */
    none,none,none,none,                /* E8-EB ? ? ? ? */
    none,none,none,none,                /* EC-EF ? ? ? ? */
    none,none,none,none,                /* F0-F3 ? ? ? ? */
    none,none,none,none,                /* F4-F7 ? ? ? ? */
    none,none,none,none,                /* F8-FB ? ? ? ? */
    none,none,none,none                 /* FC-FF ? ? ? ? */
};

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    irq_install_handler(1, keyboard_interrupt);
}
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Keyboard PS/2 to main

Post by max »

You need to create a buffer, for example a "uint8_t buf[512]" where you either store the scancodes or already the characters of the pressed key. Then you also need a counter that remembers how many characters are in that buffer. Then you can just write a blocking "readchar" function, that does an endless loop while the counter is zero; once it is higher, you return the value from the buffer (and maybe copy the memory at buffer+1 to buffer if you want to have it FIFO).
gpsd
Posts: 10
Joined: Tue Oct 22, 2013 6:22 am
Location: Italy

Re: Keyboard PS/2 to main

Post by gpsd »

He does not work.
The variable 'ch' is wrong outside 'do_self'!
('Ch') works only with the statement 'putch' and 'puts'.
Why??
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Keyboard PS/2 to main

Post by max »

Should I now magically know what "do_self" is? ...
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Keyboard PS/2 to main

Post by iansjack »

max wrote:Should I now magically know what "do_self" is? ...
It's in the code given so only if you have a very loose definition of "magically".

OP - I'm not at all sure what your problems is; what exactly are you asking?
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: Keyboard PS/2 to main

Post by max »

iansjack wrote:
max wrote:Should I now magically know what "do_self" is? ...
It's in the code given so only if you have a very loose definition of "magically".
I didn't read all the 82857 lines of code he posted, but..
iansjack wrote:OP - I'm not at all sure what your problems is; what exactly are you asking?
thats what i asked myself, too. ;)
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: Keyboard PS/2 to main

Post by Bender »

iansjack wrote:OP - I'm not at all sure what your problems is; what exactly are you asking?
I think what he's trying to say is that he wants his "readkey()" (or similar) to return the fetched key (scancode possibly) to main(), I'm not so sure becuase it will then be a very trivial question to ask, cause that's one of the first things that are taught in a C Crash course.
gdps: As others have said, please try to elaborate more on the topic. From your current explanation it's very difficult to understand what your problem is.
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
gpsd
Posts: 10
Joined: Tue Oct 22, 2013 6:22 am
Location: Italy

Re: Keyboard PS/2 to main

Post by gpsd »

The problem is the following:
When I function from the 'keyboard', I ask you to give me back the value (to work in the main) can not do "return" from function 'keyboard' to 'main'. The only work that it can do, is to print the character mapped directly from 'keyboard' function

Code: Select all

putch (ch);
I would like a

Code: Select all

return ch;
Sorry but my English is poor! :)
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: Keyboard PS/2 to main

Post by Combuster »

can not do "unreadable colours" from function 'keyboard' to 'main'.
Sounds like you have never heard of forum rules or global variables.
"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 ]
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Keyboard PS/2 to main

Post by iansjack »

gpsd wrote: I would like a

Code: Select all

return ch;
Sorry but my English is poor! :)
I still don't understand what is stopping you doing that (apart from the fact that you have declared the return type of the function as void).
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Keyboard PS/2 to main

Post by Brendan »

Hi,
gpsd wrote:

Code: Select all

void keyboard_interrupt(void) {
...

Code: Select all

        return key_table[scancode](scancode);
If this code compiles (without any sort of "OMG this mess tries to return something from a function that returns void" error), then your compiler is broken/dangerous, and you should delete the compiler and never use it for anything ever again.

Also, you can not return anything from an IRQ handler.

Instead:
  • If your OS is good and has some form of IPC (Inter-Process Communication - e.g. pipes, messages, etc), then your keyboard IRQ handler should use your IPC to send keypresses to wherever they should go (e.g. virtual terminal layer or GUI or whatever). This may mean something like "STDIN" (*nix style, using pipes) or it could be something modern like keyboard events. In any case, it should include the ability for a task to block (use no CPU time, scheduler does other things) until data has arrived.
  • If your OS is currently bad and does not have any IPC but you want it to be good one day; then you need to implement some sort of IPC before bothering with device drivers.
  • If your OS is permanently bad and will never have any IPC (e.g. MS-DOS); then implement some sort of FIFO queue to store keypresses, such that the keyboard IRQ handler stores keypresses in the FIFO and something else does "while(keyboardFIFOempty) { wait(); }" before removing/returning the keypress.

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Keyboard PS/2 to main

Post by sortie »

Brendan: I can confirm that GCC accepts (as a GNU extension enabled unless -pedantic) return statements with an expression in function with void return type, but only if the return expression has type void. This is a perfectly reasonable extension suitable for limited cases.

Code: Select all

void foo() { }
void bar() { return foo(); }
gpsd: I think the main problem with your design is that you use function pointers. Code is data. Convert each table entry from { function-pointer } to { type, argument } and then use a switch to process the entries. A simple naive approach is that you could have 2^N columns in the table for N modifier keys (such as shift and caps lock). If the number of scancodes and modifier keys are low, this is not too memory inefficient for practical use.
Post Reply