root / lab3 / lab3.c @ 15
History | View | Annotate | Download (8.16 KB)
1 | 10 | up20180645 | |
---|---|---|---|
2 | 8 | up20180645 | #include <lcom/lcf.h> |
3 | #include <lcom/lab3.h> |
||
4 | #include <stdbool.h> |
||
5 | #include <stdint.h> |
||
6 | 12 | up20180645 | #include "timer.h" |
7 | 9 | up20180645 | #include "keyboard.h" |
8 | 10 | up20180645 | |
9 | |||
10 | 8 | up20180645 | int main(int argc, char *argv[]) { |
11 | // sets the language of LCF messages (can be either EN-US or PT-PT)
|
||
12 | lcf_set_language("EN-US");
|
||
13 | |||
14 | // enables to log function invocations that are being "wrapped" by LCF
|
||
15 | // [comment this out if you don't want/need it]
|
||
16 | lcf_trace_calls("/home/lcom/labs/lab3/trace.txt");
|
||
17 | |||
18 | // enables to save the output of printf function calls on a file
|
||
19 | // [comment this out if you don't want/need it]
|
||
20 | lcf_log_output("/home/lcom/labs/lab3/output.txt");
|
||
21 | |||
22 | // handles control over to LCF
|
||
23 | // [LCF handles command line arguments and invokes the right function]
|
||
24 | if (lcf_start(argc, argv))
|
||
25 | return 1; |
||
26 | |||
27 | // LCF clean up tasks
|
||
28 | // [must be the last statement before return]
|
||
29 | lcf_cleanup(); |
||
30 | |||
31 | return 0; |
||
32 | } |
||
33 | |||
34 | 10 | up20180645 | extern uint8_t scan_code;
|
35 | extern uint32_t cnt;
|
||
36 | 12 | up20180645 | extern int count; |
37 | 9 | up20180645 | |
38 | 8 | up20180645 | int(kbd_test_scan)() {
|
39 | 12 | up20180645 | |
40 | 9 | up20180645 | int r, ipc_status;
|
41 | 10 | up20180645 | uint8_t keyboard_irq, size, bytes[2]; //size of scancode can be 2 byte long |
42 | 9 | up20180645 | message msg; |
43 | bool make=false; //to check if code is make or break |
||
44 | 8 | up20180645 | |
45 | 12 | up20180645 | if(kbc_subscribe_int(&keyboard_irq)!=0){ //check if subscription worked |
46 | 9 | up20180645 | printf("Error subscribing int\n");
|
47 | return 1; |
||
48 | } |
||
49 | |||
50 | 12 | up20180645 | while(scan_code!=ESC_BREAK){ //looping until scan_code is the breakcode of ESC key |
51 | |||
52 | 9 | up20180645 | if ((r = driver_receive(ANY, &msg, &ipc_status))==1){ |
53 | printf("driver_receive failed with: %d",r);
|
||
54 | continue;
|
||
55 | } |
||
56 | 12 | up20180645 | if (is_ipc_notify(ipc_status)){ //received notification |
57 | 9 | up20180645 | switch (_ENDPOINT_P(msg.m_source)){
|
58 | 12 | up20180645 | case HARDWARE: //hardware interrupt notification |
59 | if (msg.m_notify.interrupts &keyboard_irq){ // subscribed interrupt |
||
60 | 9 | up20180645 | |
61 | kbc_ih(); |
||
62 | bytes[0]=scan_code;
|
||
63 | bytes[1]=scan_code;
|
||
64 | |||
65 | if(bytes[0]==TWO_BYTE_SCANCODE){ |
||
66 | size=2;
|
||
67 | } |
||
68 | else{
|
||
69 | size=1;
|
||
70 | } |
||
71 | |||
72 | 10 | up20180645 | if (scan_code & MAKE_CODE){ //checks if code is make or break |
73 | 12 | up20180645 | make = false; //is break code |
74 | 9 | up20180645 | } |
75 | else {
|
||
76 | 12 | up20180645 | make = true; //is make code |
77 | 9 | up20180645 | } |
78 | 11 | up20180645 | |
79 | 12 | up20180645 | if(kbd_print_scancode(make, size, bytes)!=0){ //prints the code |
80 | 11 | up20180645 | printf("Error printing scan code\n");
|
81 | return 1; |
||
82 | } |
||
83 | 9 | up20180645 | } |
84 | break;
|
||
85 | default:
|
||
86 | 12 | up20180645 | break; //no other notifications expected: do nothing |
87 | 9 | up20180645 | } |
88 | } |
||
89 | 12 | up20180645 | else { //received a standard message, not a notification |
90 | 9 | up20180645 | //no standard messages expected: do nothing
|
91 | } |
||
92 | } |
||
93 | |||
94 | 12 | up20180645 | if (kbc_unsubscribe_int() != 0) { //check if unsubscription worked |
95 | 9 | up20180645 | printf("Error unsubscribing int \n");
|
96 | return 1; |
||
97 | } |
||
98 | |||
99 | 12 | up20180645 | if(kbd_print_no_sysinb(cnt)!=0){ //prints the number of sys calls |
100 | 11 | up20180645 | printf("Error printing number of sys used\n");
|
101 | return 1; |
||
102 | } |
||
103 | 10 | up20180645 | |
104 | 11 | up20180645 | cnt=0;
|
105 | scan_code=0;
|
||
106 | |||
107 | 9 | up20180645 | return 0; |
108 | 8 | up20180645 | } |
109 | |||
110 | int(kbd_test_poll)() {
|
||
111 | 12 | up20180645 | |
112 | 11 | up20180645 | uint8_t status, size, bytes[2]; //size of scancode can be 2 byte long |
113 | bool make=false; //to check if code is make or break |
||
114 | 8 | up20180645 | |
115 | 12 | up20180645 | while(scan_code!=ESC_BREAK){ //looping until scan_code is the breakcode of ESC key, can't do interruptions |
116 | |||
117 | 11 | up20180645 | if(util_sys_inb(STATUS_REG, &status)!=0){ //checks the status register |
118 | printf("Error reading status register\n");
|
||
119 | return 1; |
||
120 | } |
||
121 | |||
122 | 12 | up20180645 | 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 |
123 | 11 | up20180645 | |
124 | 12 | up20180645 | if(util_sys_inb(OUTPUT_BUF, &scan_code)!=0){ //reads output buffer |
125 | 11 | up20180645 | printf("Error reading output buffer\n");
|
126 | return 1; |
||
127 | } |
||
128 | |||
129 | bytes[0]=scan_code;
|
||
130 | bytes[1]=scan_code;
|
||
131 | |||
132 | if(bytes[0]==TWO_BYTE_SCANCODE){ |
||
133 | size=2;
|
||
134 | } |
||
135 | else{
|
||
136 | size=1;
|
||
137 | } |
||
138 | |||
139 | if (scan_code & MAKE_CODE){ //checks if code is make or break |
||
140 | make = false; //break code |
||
141 | } |
||
142 | else {
|
||
143 | make = true; //make code |
||
144 | } |
||
145 | |||
146 | if(kbd_print_scancode(make, size, bytes)!=0){ //prints the code |
||
147 | printf("Error printing scan code\n");
|
||
148 | return 1; |
||
149 | } |
||
150 | |||
151 | } |
||
152 | else { //if the output buffer is not full wait |
||
153 | tickdelay(micros_to_ticks(DELAY_US)); //makes keyboard respond to a command in 20 ms
|
||
154 | } |
||
155 | } |
||
156 | |||
157 | 12 | up20180645 | if(kbd_print_no_sysinb(cnt)!=0){ //prints the number of sys calls |
158 | 11 | up20180645 | printf("Error printing number of sys used\n");
|
159 | return 1; |
||
160 | } |
||
161 | |||
162 | 12 | up20180645 | if(reenable_interrupt()!=0){ //re-enables interruptions |
163 | printf("Couldn't re-enable the interruptions\n");
|
||
164 | 11 | up20180645 | return 1; |
165 | |||
166 | } |
||
167 | cnt=0;
|
||
168 | scan_code=0;
|
||
169 | |||
170 | return 0; |
||
171 | 8 | up20180645 | } |
172 | |||
173 | |||
174 | 12 | up20180645 | int(kbd_test_timed_scan)(uint8_t n) { //similar function to that of test_time_scan but with timer interruptions |
175 | |||
176 | if(n<0){ //checks if n is a valid input |
||
177 | printf("Invalid time\n");
|
||
178 | return 1; |
||
179 | } |
||
180 | |||
181 | int r, ipc_status;
|
||
182 | uint8_t keyboard_irq, size, bytes[2], timer_irq; //size of scancode can be 2 byte long |
||
183 | message msg; |
||
184 | bool make=false; //to check if code is make or break |
||
185 | |||
186 | if(timer_subscribe_int(&timer_irq)!=0){ |
||
187 | printf("Error subscribing int (timer)\n");
|
||
188 | return 1; |
||
189 | } |
||
190 | |||
191 | if(kbc_subscribe_int(&keyboard_irq)!=0){ |
||
192 | printf("Error subscribing int (keyboard)\n");
|
||
193 | return 1; |
||
194 | } |
||
195 | |||
196 | while((scan_code!=ESC_BREAK)&&(count/sys_hz()<n)){ //looping until scan_code is the breakcode of ESC key or until a command is issued within the time interval |
||
197 | if ((r = driver_receive(ANY, &msg, &ipc_status))==1){ |
||
198 | printf("driver_receive failed with: %d",r);
|
||
199 | continue;
|
||
200 | } |
||
201 | if (is_ipc_notify(ipc_status)){ //received notification |
||
202 | switch (_ENDPOINT_P(msg.m_source)){
|
||
203 | case HARDWARE: //hardware interrupt notification |
||
204 | if (msg.m_notify.interrupts &keyboard_irq){ // subscribed interrupt (keyboard) |
||
205 | |||
206 | kbc_ih(); |
||
207 | bytes[0]=scan_code;
|
||
208 | bytes[1]=scan_code;
|
||
209 | |||
210 | if(bytes[0]==TWO_BYTE_SCANCODE){ |
||
211 | size=2;
|
||
212 | } |
||
213 | else{
|
||
214 | size=1;
|
||
215 | } |
||
216 | |||
217 | if (scan_code & MAKE_CODE){ //checks if code is make or break |
||
218 | make = false; //break code |
||
219 | } |
||
220 | else {
|
||
221 | make = true; //make code |
||
222 | } |
||
223 | |||
224 | if(kbd_print_scancode(make, size, bytes)!=0){ //prints the code |
||
225 | printf("Error printing scan code\n");
|
||
226 | return 1; |
||
227 | } |
||
228 | count=0; //resets counter, since a keyboard interruption has ocurred |
||
229 | } |
||
230 | else if (msg.m_notify.interrupts &timer_irq) { // subscribed interrupt (timer) |
||
231 | timer_int_handler(); //if a timer interruption occurs increment timer
|
||
232 | } |
||
233 | break;
|
||
234 | default:
|
||
235 | break; //no other notifications expected: do nothing |
||
236 | } |
||
237 | } |
||
238 | else { //received a standard message, not a notification |
||
239 | //no standard messages expected: do nothing
|
||
240 | } |
||
241 | } |
||
242 | |||
243 | if (kbc_unsubscribe_int() != 0) { //check if unsubscription worked |
||
244 | printf("Error unsubscribing int \n");
|
||
245 | return 1; |
||
246 | } |
||
247 | |||
248 | if(timer_unsubscribe_int()!=0){ //check if unsubscription worked |
||
249 | printf("Error unsubscribing int\n");
|
||
250 | return 1; |
||
251 | } |
||
252 | |||
253 | if(kbd_print_no_sysinb(cnt)!=0){ //prints the number of sys calls |
||
254 | printf("Error printing number of sys used\n");
|
||
255 | return 1; |
||
256 | } |
||
257 | |||
258 | cnt=0;
|
||
259 | scan_code=0;
|
||
260 | |||
261 | return 0; |
||
262 | 8 | up20180645 | } |