Advertisement
Guest User

Untitled

a guest
Mar 25th, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.43 KB | None | 0 0
  1. #include "lib.h"
  2. #include "i8259.h"
  3. #include "keyboard.h"
  4.  
  5. // Sets a bit in bitfield based on set (sets the bit if set is truthy)
  6. // The input flag should be a binary number containing only one 1
  7. //  which indicates which bit to set
  8. #define SET_BIT(bitfield, flag, set) \
  9. do {                                 \
  10.     if ((set))                       \
  11.         bitfield |= (flag);          \
  12.     else                             \
  13.         bitfield &= (~(flag));       \
  14. } while (0)
  15.  
  16. /* Stores information about the current status of the keyboard (shift, caps lock, ctrl, alt)*/
  17. static unsigned int keyboard_key_status = 0;
  18.  
  19. /*flag that is 1 until it enter is pressed*/
  20. volatile unsigned int enter_flag = 1;
  21.  
  22. /* store the position of where to store next linebuffer character */
  23. static unsigned int linepos = 0;
  24.  
  25. /*store whether keyboard has been initialized or not*/
  26. static unsigned int keyboard_init = 0;
  27.  
  28. //line buffer to store everything typed into terminal
  29. unsigned char linebuffer[(TERMINAL_SIZE)];
  30.  
  31. //for open,close,read,write
  32. #define RTC_PASS 0
  33. #define RTC_FAIL -1
  34.  
  35. /* KBDUS means US Keyboard Layout.
  36.  * CREDIT TO http://www.osdever.net/bkerndev/Docs/keyboard.htm
  37.  * where we got the following scancode to ascii mapping */
  38.  
  39. // Array mapping keyboard scan codes to ASCII characters
  40. const unsigned char kbdus[128] = {
  41.     0,  27,
  42.     '1', '2', '3', '4', '5', '6', '7', '8','9', '0', '-', '=', '\b' /* Backspace */,
  43.     '\t' /* Tab */,
  44.     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n' /* Enter key */,
  45.     0,                                                  /* 29   - Control */
  46.     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',   /* 39 */
  47.     '\'', '`',   0,                                     /* Left shift */
  48.     '\\', 'z', 'x', 'c', 'v', 'b', 'n',                 /* 49 */
  49.     'm', ',', '.', '/',   0,                            /* Right shift */
  50.     '*',
  51.     0,      /* Alt */
  52.     ' ',    /* Space bar */
  53.     0,      /* Caps lock */
  54.     0,      /* 59 - F1 key ... > */
  55.     0,   0,   0,   0,   0,   0,   0,   0,
  56.     0,      /* < ... F10 */
  57.     0,      /* 69 - Num lock*/
  58.     0,      /* Scroll Lock */
  59.     0,      /* Home key */
  60.     0,      /* Up Arrow */
  61.     0,      /* Page Up */
  62.     '-',
  63.     0,      /* Left Arrow */
  64.     0,
  65.     0,      /* Right Arrow */
  66.     '+',
  67.     0,      /* 79 - End key*/
  68.     0,      /* Down Arrow */
  69.     0,      /* Page Down */
  70.     0,      /* Insert Key */
  71.     0,      /* Delete Key */
  72.     0,   0,   0,
  73.     0,      /* F11 Key */
  74.     0,      /* F12 Key */
  75.     0,      /* All other keys are undefined */
  76. };
  77.  
  78. /* Array mapping keyboard scan codes to ASCII characters when the shift key is pressed*/
  79. const unsigned char shift_kbdus[128] = {
  80.     0,  27,
  81.     '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
  82.     '\t',                                               /*Tab*/
  83.     'Q', 'W', 'E', 'R',                                 /* 19 */
  84.     'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',       /* Enter key */
  85.     0,                                                  /* 29   - Control */
  86.     'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',   /* 39 */
  87.     '\"', '~',   0,                                     /* Left shift */
  88.     '|', 'Z', 'X', 'C', 'V', 'B', 'N',                 /* 49 */
  89.     'M', '<', '>', '?',   0,                            /* Right shift */
  90.     '*',
  91.     0,      /* Alt */
  92.     ' ',    /* Space bar */
  93.     0,      /* Caps lock */
  94.     0,      /* 59 - F1 key ... > */
  95.     0,   0,   0,   0,   0,   0,   0,   0,
  96.     0,      /* < ... F10 */
  97.     0,      /* 69 - Num lock*/
  98.     0,      /* Scroll Lock */
  99.     0,      /* Home key */
  100.     0,      /* Up Arrow */
  101.     0,      /* Page Up */
  102.     '-',
  103.     0,      /* Left Arrow */
  104.     0,
  105.     0,      /* Right Arrow */
  106.     '+',
  107.     0,      /* 79 - End key*/
  108.     0,      /* Down Arrow */
  109.     0,      /* Page Down */
  110.     0,      /* Insert Key */
  111.     0,      /* Delete Key */
  112.     0,   0,   0,
  113.     0,      /* F11 Key */
  114.     0,      /* F12 Key */
  115.     0,      /* All other keys are undefined */
  116. };
  117.  
  118. /*
  119.  * Initializes keyboard and enables keyboard interrupt
  120.  *
  121.  * INPUTS: none
  122.  * OUTPUTS: none
  123.  * SIDE EFFECTS: enables interrupts for keyboard
  124.  */
  125. void init_keyboard() {
  126.     unsigned char ccb;
  127.     int i;/*used for loop*/
  128.  
  129.     // Read value of CCB
  130.     outb(CCB_READ, KEYBOARD_CONTROLLER_STATUS_PORT);
  131.     ccb = inb(KEYBOARD_CONTROLLER_DATA_PORT);
  132.  
  133.     // Update CCB to enable keyboard interrupts
  134.     ccb |= KEYBOARD_INTERRUPT_ENABLE | TRANSLATE_KEYBOARD_SCANCODE | DISABLE_MOUSE;
  135.  
  136.     // Write update value to CCB
  137.     outb(CCB_WRITE, KEYBOARD_CONTROLLER_STATUS_PORT);
  138.     outb(ccb, KEYBOARD_CONTROLLER_DATA_PORT);
  139.  
  140.     // Enable interrupt after all setup is complete
  141.     enable_irq(KEYBOARD_IRQ);
  142.  
  143.     //initialize line buffer
  144.     for(i = 0; i < 128;i++) {
  145.       linebuffer[i] = '\0';
  146.     }
  147.     //update cursor to point at beginning
  148.     update_cursor();
  149.     //say keyboard_init is done
  150.     keyboard_init = 1;
  151. }
  152.  
  153. /*
  154.  * Reads the scancode from the keyboard port and outputs to the console correctly
  155.  *
  156.  * INPUTS: none
  157.  * OUTPUTS: none
  158.  * SIDE EFFECTS: outputs a key to the console when the keyboard interrupt is fired
  159.  */
  160. void keyboard_handler() {
  161.     unsigned char scancode;
  162.     unsigned char key_down;
  163.  
  164.     /*Check for shift,ctrl,alt,CapsLock,Backspace, and tab*/
  165.     unsigned char is_shift, is_ctrl, is_alt, is_caps_lock, is_backspace, is_tab;
  166.  
  167.     /*Used for loops later*/
  168.     int i;
  169.  
  170.     /*keeps track of if ctrl+L was clicked*/
  171.     int ctrlL = 0;
  172.  
  173.     /*Read the scan code and check if it corresponds to a key press or a key release */
  174.     scancode = inb(KEYBOARD_CONTROLLER_DATA_PORT);
  175.     key_down = ((scancode & KEY_DOWN_MASK) == 0);
  176.  
  177.     /*Check if the keys are either shift, ctrl, alt, caps lock, tab, or backspace*/
  178.     is_shift     = ((scancode & SCAN_CODE_MASK) == LEFT_SHIFT_CODE || (scancode & SCAN_CODE_MASK) == RIGHT_SHIFT_CODE);
  179.     is_ctrl      = ((scancode & SCAN_CODE_MASK) == LEFT_CTRL_CODE);
  180.     is_alt       = ((scancode & SCAN_CODE_MASK) == LEFT_ALT_CODE);
  181.     is_caps_lock = ((scancode & SCAN_CODE_MASK) == CAPS_LOCK_CODE);
  182.     is_backspace = ((scancode & SCAN_CODE_MASK) == BACKSPACE_CODE);
  183.     is_tab       = ((scancode & SCAN_CODE_MASK) == TAB_CODE);
  184.     // Set shift, ctrl, alt based on whether the key is down or up
  185.     if (is_shift) SET_BIT(keyboard_key_status, SHIFT, key_down);
  186.     if (is_ctrl)  SET_BIT(keyboard_key_status, CTRL,  key_down);
  187.     if (is_alt)   SET_BIT(keyboard_key_status, ALT,   key_down);
  188.  
  189.     // Set caps lock to the opposite of what it was
  190.     if (is_caps_lock && key_down)
  191.         SET_BIT(keyboard_key_status, CAPS_LOCK, !(keyboard_key_status & CAPS_LOCK));
  192.  
  193.  
  194.     /*check for ctrl+ something command*/
  195.     if( (keyboard_key_status & CTRL) != 0) {
  196.         /*all CTRL+ commands HERE*/
  197.  
  198.         /*if CTRL+L
  199.           clear screen and put cursor in upper right corner*/
  200.         if(kbdus[(scancode & SCAN_CODE_MASK)] == 'l') {
  201.             set_color(V_BLACK,V_CYAN);
  202.             clear();
  203.             /*print linebuffer*/
  204.             for(i = 0; i <= linepos;i++) {
  205.                 /*print 3 spaces for tab*/
  206.                 if(linebuffer[i] == '\t') {
  207.                     putc(' ');
  208.                     putc(' ');
  209.                     putc(' ');
  210.                 }
  211.                 /*move 1 ahead b/c linebuffer[127] = '\n'*/
  212.                 else if(i == 127) {
  213.                     increment_location();
  214.                     continue;
  215.                 }
  216.                 else
  217.                   putc(linebuffer[i]);
  218.             }
  219.             //set CTRL+L to pressed
  220.             ctrlL = 1;
  221.             /*in the end decrement location so blinking cursor
  222.               is at correct location*/
  223.             decrement_location();
  224.  
  225.         }
  226.  
  227.     }
  228.  
  229.  
  230.  
  231.     // If the character is alphabetical:
  232.     // The printed character should be uppercase if either shift or caps lock is on (but not both, hence the XOR)
  233.     unsigned char uppercase = ((keyboard_key_status & SHIFT) != 0) ^ ((keyboard_key_status & CAPS_LOCK) != 0);
  234.  
  235.     // If the character is not alphabetical:
  236.     // Whether or not to use the shifted character set
  237.     unsigned char use_shift = ((keyboard_key_status & SHIFT) != 0);
  238.  
  239.     // Print the character
  240.     char character = kbdus[scancode & SCAN_CODE_MASK];
  241.     char is_alphabetical = (character >= 'a' && character <= 'z');
  242.     if(character == '\n' && key_down)
  243.         enter_flag = 0;
  244.  
  245.     /*BACKSPACE
  246.       Clear 1 byte back in memory*/
  247.     if(is_backspace && key_down && linepos >= 0 && linepos < 127 && linebuffer[linepos] != '\n') {
  248.         /*if buffer is full, remove \n and previous char*/
  249.         /*set color*/
  250.         set_color(V_BLACK,V_CYAN);
  251.         /*call on clear_char*/
  252.         clear_char();
  253.         /*clear keyboard buffer at linepos*/
  254.         linebuffer[linepos] = '\0';
  255.         /*decrement linepos*/
  256.         if(linepos > 0) {
  257.             linepos--;
  258.         }
  259.     }
  260.  
  261.     if (key_down) {
  262.  
  263.         // Use the shifted set if it's alphabetical and uppercase
  264.         //   OR if it's non alphabetical but the shift key is down
  265.         if((is_alphabetical && uppercase) || (!is_alphabetical && use_shift))
  266.             character = shift_kbdus[scancode & SCAN_CODE_MASK];
  267.  
  268.         /* Only print the character if:
  269.          *    - character is not 0
  270.          *    - backspace is NOT being used
  271.          *    - terminal buffer is NOT full
  272.          */
  273.         if (character && ctrlL == 0 && (!is_backspace) && (linepos < 127)) {
  274.             //if it's a tab, print 3 spaces
  275.             if(is_tab && key_down) {
  276.                 putc(' ');
  277.                 putc(' ');
  278.                 putc(' ');
  279.             }
  280.             else {
  281.                 putc(character);
  282.             }
  283.             //store character into line
  284.             linebuffer[linepos] = character;
  285.             linepos++;
  286.             update_cursor();
  287.         }
  288.         /*if buffer is full, then put \n as last character*/
  289.         else if(linepos == 127) {
  290.             character = '\n';
  291.             linebuffer[linepos] = character;
  292.             enter_flag = 0;
  293.         }
  294.  
  295.     }
  296.  
  297.     // Send EOI
  298.     send_eoi(KEYBOARD_IRQ);
  299. }
  300.  
  301. /*
  302.  * initializes vairables if needed and if keyboard
  303.  * has not been initialized, initialize it
  304.  *
  305.  * INPUTS: none
  306.  * OUTPUTS: 0, to indicate it went well
  307.  * SIDE EFFECTS: modifies linebuffer
  308.  */
  309. int32_t terminal_open(void) {
  310.     int32_t i;
  311.     if(!keyboard_init)
  312.         init_keyboard();
  313.     for(i = 0; i < 128;i++) {
  314.         linebuffer[i] = '\0';
  315.     }
  316.     update_cursor();
  317.     return TERMINAL_PASS;
  318. }
  319.  
  320. /*
  321.  * closes vairables if needed
  322.  * INPUTS: none
  323.  * OUTPUTS: 0, to indicate it went well
  324.  * SIDE EFFECTS: nothing
  325.  */
  326. int32_t terminal_close(void) {
  327.     return TERMINAL_PASS;
  328. }
  329.  
  330. /*
  331.  * initializes vairables if needed and if keyboard
  332.  * has not been initialized, initialize it
  333.  * INPUTS: int32_t fd = file descriptor
  334.             char* buf = buffer to copy into
  335.            int32_t bytes = number of bytes to copy into buf
  336.  * OUTPUTS: 0, to indicate it went well
  337.  * SIDE EFFECTS: modifies linwbuffer
  338.  */
  339. int32_t terminal_read(int32_t fd, char* buf, int32_t bytes) {
  340.     /*if userspace to copy into is NULL, can't write anything
  341.     into NULL.*/
  342.     if(buf == NULL || bytes < 0)
  343.         return TERMINAL_FAIL;
  344.     /*if 0 bytes to copy, do nothing*/
  345.     else if(bytes == 0)
  346.         return TERMINAL_PASS;
  347.  
  348.  
  349.     /*let the program spin until an enter has been pressed*/
  350.     while(enter_flag) {}
  351.     enter_flag = 1;
  352.     /*if the bytes to read > TERMINAL_SIZE supported,
  353.      just copy the the number of bytes possible.*/
  354.     cli();
  355.     if(bytes > TERMINAL_SIZE)
  356.         bytes = TERMINAL_SIZE;
  357.     /* if bytes to read is moe than wahts being read from keyboard,
  358.        set bytes to what's been read so far*/
  359.     if(bytes > linepos+1)
  360.         bytes = linepos;
  361.     /* loop over possible loop to copy into userspace buf */
  362.     int i;
  363.     for(i = 0; i < bytes;i++) {
  364.         //if linebuffer reaches \n, buf should only
  365.         //contain that much
  366.         if(linebuffer[i] != '\n') {
  367.             buf[i] = linebuffer[i];
  368.         }
  369.         else {
  370.             buf[i] = '\0';
  371.             bytes = i;
  372.             break;
  373.         }
  374.  
  375.     }
  376.  
  377.     int index;
  378.     /* clear remaining characters written into userspace*/
  379.     for(i = 0, index = bytes+1; index < TERMINAL_SIZE;index++)
  380.         linebuffer[i++] = linebuffer[index];
  381.     while(i < TERMINAL_SIZE) {
  382.         linebuffer[i] = '\0';
  383.         i++;
  384.     }
  385.     if(linepos == 127 && bytes == 127) {
  386.         linepos-=bytes;
  387.     }
  388.     linepos-=(bytes+1);
  389.  
  390.     sti();
  391.     return bytes;
  392. }
  393.  
  394. /*
  395.  * initializes vairables if needed and if keyboard
  396.  * has not been initialized, initialize it
  397.  * INPUTS: none
  398.  * OUTPUTS: 0, to indicate it went well
  399.  * SIDE EFFECTS: modifies linwbuffer
  400.  */
  401. int32_t terminal_write(int32_t fd, const char* buf, int32_t bytes) {
  402.     int i;
  403.     //if buf is NULL or bytes is negative, function can't complete
  404.     if(buf == NULL || bytes < 0)
  405.         return TERMINAL_FAIL;
  406.     //if it's 0, then 0 bytes are written to terminal, PASS
  407.     if(bytes == 0)
  408.         return TERMINAL_PASS;
  409.     //start new line before writing
  410.     //putc('\n');
  411.     for(i = 0; i < bytes;i++) {
  412.         /*should end at \n, but if it is end of string,
  413.           print it out*/
  414.         if(buf[i] != '\n' && buf[i] != '\0') {
  415.             putc(buf[i]);
  416.         }
  417.         else
  418.             break;
  419.  
  420.     }
  421.     //end with new line
  422.     //putc('\n');
  423.     return TERMINAL_PASS;
  424.  
  425. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement