Revision 11
Added function 5.2, must check for errors
lab3/i8042.h | ||
---|---|---|
24 | 24 |
#define STAT_REG_IBF BIT(1) /* Input Buffer Full */ |
25 | 25 |
#define STAT_REG_OBF BIT(0) /* Output Buffer Full */ |
26 | 26 |
|
27 |
#define READ_COMMAND 0x20 /* Returns Command Byte */ |
|
28 |
|
|
27 | 29 |
#define OUTPUT_BUF 0x60 /* Output Buffer */ |
28 | 30 |
#define INPUT_BUF 0x60 /* Input Buffer */ |
29 |
#define STATUS_REG 0x64 /* Status Register */ |
|
30 |
#define KBC_CMD_REG 0x64 /* Command Register */ |
|
31 |
#define KBC_CMD_ARG 0x60 /* Command Arguments Adress */ |
|
31 |
#define STATUS_REG 0x64 /* Status Register */ |
|
32 |
#define KBC_CMD_REG 0x64 /* Command Register */ |
|
33 |
#define INT_ENABLE BIT(0) /*enable interrupt on OBF, from keyboard*/ |
|
34 |
#define KBC_CMD_ARG 0x60 /* Command Arguments Adress */ |
|
32 | 35 |
|
33 |
#define ESC_BREAK 0x81 |
|
36 |
#define ESC_BREAK 0x81
|
|
34 | 37 |
#define TWO_BYTE_SCANCODE 0xE0 /* Two-byte long scancodes use 0xE0 as their first byte */ |
35 |
#define MAKE_CODE BIT(7)
|
|
38 |
#define MAKE_CODE BIT(7) |
|
36 | 39 |
|
37 | 40 |
#endif /* _LCOM_I8042_H */ |
lab3/keyboard.c | ||
---|---|---|
26 | 26 |
if(util_sys_inb(STATUS_REG,&status_reg)!=0){ //checks if there is an error |
27 | 27 |
return; |
28 | 28 |
} |
29 |
if(((status_reg & STAT_REG_OBF)==0) ||((status_reg&(STAT_REG_PAR|STAT_REG_TIMEOUT))!=0)){ //checks if there is a parity or timeout error (mask -> 0xC0, bit 7 and 6 set) and checks if output buffer is empty
|
|
29 |
if(((status_reg & STAT_REG_OBF)==0) ||((status_reg&(STAT_REG_PAR|STAT_REG_TIMEOUT))!=0)|| ((status_reg&STAT_REG_AUX)!=0)){ //checks if there is a parity or timeout error (mask -> 0xC0, bit 7 and 6 set), checks if output buffer is empty and checks if there is data coming from the mouse
|
|
30 | 30 |
return; |
31 | 31 |
} |
32 | 32 |
util_sys_inb(OUTPUT_BUF,&scan_code); |
33 | 33 |
|
34 | 34 |
} |
35 | 35 |
|
36 |
|
|
36 | 37 |
int (kbc_subscribe_int)(uint8_t *bit_no) { //similar function to that of timer_subscribe_int |
37 | 38 |
*bit_no = BIT(keyboard_id); |
38 | 39 |
if(sys_irqsetpolicy(KEYBOARD_IRQ,(IRQ_REENABLE|IRQ_EXCLUSIVE),&keyboard_id)==1){ //operation to subscribe int |
... | ... | |
49 | 50 |
} |
50 | 51 |
return 0; |
51 | 52 |
} |
53 |
|
|
54 |
int (enable_interrupt)() |
|
55 |
{ |
|
56 |
uint8_t command; |
|
57 |
|
|
58 |
if(sys_outb(STATUS_REG,READ_COMMAND)!=0){ |
|
59 |
printf("Error writing read-command\n"); |
|
60 |
return 1; |
|
61 |
} |
|
62 |
|
|
63 |
if(util_sys_inb(OUTPUT_BUF, &command)!=0){ |
|
64 |
printf("Error reading output buffer\n"); |
|
65 |
return 1; |
|
66 |
} |
|
67 |
|
|
68 |
command = command | INT_ENABLE; |
|
69 |
|
|
70 |
if(sys_outb(STATUS_REG,OUTPUT_BUF)!=0){ |
|
71 |
printf("Error writing output buffer\n"); |
|
72 |
return 1; |
|
73 |
} |
|
74 |
|
|
75 |
if(sys_outb(OUTPUT_BUF,command)!=0){ |
|
76 |
printf("Error writing new buffer status\n"); |
|
77 |
return 1; |
|
78 |
} |
|
79 |
|
|
80 |
return 0; |
|
81 |
} |
lab3/keyboard.h | ||
---|---|---|
5 | 5 |
#include <lcom/lcf.h> |
6 | 6 |
#include <stdbool.h> |
7 | 7 |
#include <stdint.h> |
8 |
#include <minix/syslib.h> |
|
9 |
#include <minix/sysutil.h> |
|
8 | 10 |
|
9 | 11 |
#include "i8042.h" |
10 | 12 |
/** |
11 |
* @brief Handles keyboard interrupts (C implementation)
|
|
13 |
* @brief Handles keyboard interrupts |
|
12 | 14 |
* |
13 |
* Reads the status register and the output buffer (OB).
|
|
14 |
* If there was some error, the byte read from the OB should be discarded.
|
|
15 |
* Reads the status register, the output buffer and the mouse data
|
|
16 |
* If there was some error, the byte read from the OB should be discarded |
|
15 | 17 |
* |
16 |
* All communication with other code must be done via global variables, static if possible.
|
|
18 |
* All communication with other code must be done via global variables, static if possible |
|
17 | 19 |
* |
18 | 20 |
* Must be defined using parenthesis around the function name: |
19 | 21 |
*/ |
... | ... | |
41 | 43 |
* @return Return 0 upon success and non-zero otherwise |
42 | 44 |
*/ |
43 | 45 |
int(kbc_unsubscribe_int)(); |
46 |
/** |
|
47 |
* @brief Enables interrupts (used when polling function ends) |
|
48 |
* |
|
49 |
* @return Return 0 upon success and non-zero otherwise |
|
50 |
*/ |
|
51 |
int (enable_interrupt)(); |
|
44 | 52 |
|
45 | 53 |
#endif /*_KEYBOARD_H */ |
lab3/lab3.c | ||
---|---|---|
45 | 45 |
return 1; |
46 | 46 |
} |
47 | 47 |
|
48 |
while(scan_code!=ESC_BREAK){ //looping until scann_code is the breakcode of ESC key
|
|
48 |
while(scan_code!=ESC_BREAK){ //looping until scan_code is the breakcode of ESC key |
|
49 | 49 |
if ((r = driver_receive(ANY, &msg, &ipc_status))==1){ |
50 | 50 |
printf("driver_receive failed with: %d",r); |
51 | 51 |
continue; |
52 | 52 |
} |
53 | 53 |
if (is_ipc_notify(ipc_status)){ //received notification |
54 | 54 |
switch (_ENDPOINT_P(msg.m_source)){ |
55 |
case HARDWARE: //hardware interrupt notification
|
|
55 |
case HARDWARE: //hardware interrupt notification |
|
56 | 56 |
if (msg.m_notify.interrupts &keyboard_irq){ // subscribed interrupt |
57 | 57 |
|
58 | 58 |
kbc_ih(); |
... | ... | |
72 | 72 |
else { |
73 | 73 |
make = true; //make code |
74 | 74 |
} |
75 |
kbd_print_scancode(make, size, bytes); //prints the code |
|
75 |
|
|
76 |
if(kbd_print_scancode(make, size, bytes)!=0){ //prints the code |
|
77 |
printf("Error printing scan code\n"); |
|
78 |
return 1; |
|
79 |
} |
|
76 | 80 |
} |
77 | 81 |
break; |
78 | 82 |
default: |
... | ... | |
89 | 93 |
return 1; |
90 | 94 |
} |
91 | 95 |
|
92 |
kbd_print_no_sysinb(cnt); |
|
96 |
if(kbd_print_no_sysinb(cnt)!=0){ |
|
97 |
printf("Error printing number of sys used\n"); |
|
98 |
return 1; |
|
99 |
} |
|
93 | 100 |
|
101 |
cnt=0; |
|
102 |
scan_code=0; |
|
103 |
|
|
94 | 104 |
return 0; |
95 | 105 |
} |
96 | 106 |
|
97 | 107 |
int(kbd_test_poll)() { |
98 |
/* To be completed by the students */
|
|
99 |
printf("%s is not yet implemented!\n", __func__);
|
|
108 |
uint8_t status, size, bytes[2]; //size of scancode can be 2 byte long
|
|
109 |
bool make=false; //to check if code is make or break
|
|
100 | 110 |
|
101 |
return 1; |
|
111 |
while(scan_code!=ESC_BREAK){ //looping until scan_code is the breakcode of ESC key, can't do interruptions |
|
112 |
if(util_sys_inb(STATUS_REG, &status)!=0){ //checks the status register |
|
113 |
printf("Error reading status register\n"); |
|
114 |
return 1; |
|
115 |
} |
|
116 |
|
|
117 |
if ((status & STAT_REG_OBF) && !(status & STAT_REG_AUX) && !(status & STAT_REG_PAR || status & STAT_REG_TIMEOUT)) { //checks if there is no parity ot timeout error, if the output buffer is full and if there is mouse data |
|
118 |
|
|
119 |
if(util_sys_inb(OUTPUT_BUF, &scan_code)!=0){ |
|
120 |
printf("Error reading output buffer\n"); |
|
121 |
return 1; |
|
122 |
} |
|
123 |
|
|
124 |
bytes[0]=scan_code; |
|
125 |
bytes[1]=scan_code; |
|
126 |
|
|
127 |
if(bytes[0]==TWO_BYTE_SCANCODE){ |
|
128 |
size=2; |
|
129 |
} |
|
130 |
else{ |
|
131 |
size=1; |
|
132 |
} |
|
133 |
|
|
134 |
if (scan_code & MAKE_CODE){ //checks if code is make or break |
|
135 |
make = false; //break code |
|
136 |
} |
|
137 |
else { |
|
138 |
make = true; //make code |
|
139 |
} |
|
140 |
|
|
141 |
if(kbd_print_scancode(make, size, bytes)!=0){ //prints the code |
|
142 |
printf("Error printing scan code\n"); |
|
143 |
return 1; |
|
144 |
} |
|
145 |
|
|
146 |
} |
|
147 |
else { //if the output buffer is not full wait |
|
148 |
tickdelay(micros_to_ticks(DELAY_US)); //makes keyboard respond to a command in 20 ms |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
if(kbd_print_no_sysinb(cnt)!=0){ |
|
153 |
printf("Error printing number of sys used\n"); |
|
154 |
return 1; |
|
155 |
} |
|
156 |
|
|
157 |
if(enable_interrupt()!=0){ |
|
158 |
printf("Coulnd re-enable the interruptions\n"); |
|
159 |
return 1; |
|
160 |
|
|
161 |
} |
|
162 |
cnt=0; |
|
163 |
scan_code=0; |
|
164 |
|
|
165 |
return 0; |
|
102 | 166 |
} |
103 | 167 |
|
104 | 168 |
int(kbd_test_timed_scan)(uint8_t n) { |
Also available in: Unified diff