-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkcd.c
425 lines (381 loc) · 13.7 KB
/
kcd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
#include "kcd.h"
// assuming space in between command char and each parameter
int check_parameters(char in_cmd, char* in_param) {
if(in_cmd == '\0') {
return RTX_ERROR;
}
const int buffsize = 64;
char tmp_param[buffsize];
// assume in_cmd in cmd_table
if(in_cmd == 0x57) {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] W -- wall clock \n\r");
#endif
// W
// keyboard command
if(in_param[0] == 0x53) {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] S -- set \n\r");
#endif
// S
// sets current wall clock time to param
int j = 0;
int i = 1;
while(in_param[i] == 0x20) {i++;}
while(in_param[i] != 0x20 && in_param[i] != '\0') {
tmp_param[j++] = in_param[i++];
}
tmp_param[j] = '\0';
if(j > 8) {
// though command may be correct, there is garbage appended at the end
return RTX_ERROR;
}
// format should be hh:mm:ss
// and should be a "standard" 24 hour time
// todo: check ^ and v
// should check if at null in tmp_param
if((tmp_param[0] >= 0x30) && (tmp_param[0] <= 0x32) &&
(tmp_param[1] >= 0x30) && (tmp_param[1] <= 0x34) &&
(tmp_param[2] == 0x3a) && /* : */
(tmp_param[3] >= 0x30) && (tmp_param[3] <= 0x35) &&
(tmp_param[4] >= 0x30) && (tmp_param[4] <= 0x39) &&
(tmp_param[5] == 0x3a) &&
(tmp_param[6] >= 0x30) && (tmp_param[6] <= 0x35) &&
(tmp_param[7] >= 0x30) && (tmp_param[7] <= 0x39)) {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] SUCCESS Wall Clock Time parsed correctly \n\r");
#endif
return RTX_SUCCESS;
}
else {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] ERROR In Wall Clock Time format \n\r");
#endif
return RTX_ERROR; // hh:mm:ss time format malformed
}
}
else if (in_param[0] == 0x54) {
// T
// terminate display
int i = 1;
while(in_param[i] == 0x20) {i++;}
if(in_param[i] != '\0') {
// garbage after valid input
return RTX_ERROR;
}
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] T --> SUCCESS Wall Clock Terminated \n\r");
#endif
return RTX_SUCCESS;
}
else {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] ERROR Not a recognized 'W' command \n\r");
#endif
return RTX_ERROR; // not a recognized mode for the 'W' command
}
}
else if (in_cmd == 0x43) {
// C
// set priority command
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] C -- set priority command \n\r");
#endif
int j = 0; // will count number of non ' ' chars
int i = 0;
while(in_param[i] == 0x20) {i++;} // ' '
while(in_param[i] != 0x20) {
tmp_param[j++] = in_param[i++];
}
tmp_param[j] = '\0';
int tmp_pid = atoi(tmp_param);
if(!is_valid_pid(tmp_pid)) {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] ERROR Invalid PID for set priority command \n\r");
#endif
return RTX_ERROR; // invalid pid
}
j = 0; // reset buffer by overwriting old data
while(in_param[i] == 0x20) {i++;} // ' '
while(in_param[i] != 0x20 && in_param[i] != '\0') {
tmp_param[j++] = in_param[i++];
}
tmp_param[j] = '\0';
int tmp_newpri = atoi(tmp_param);
if(!is_valid_priority(tmp_newpri)) {
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] ERROR Invalid priority for set priority command \n\r");
#endif
return RTX_ERROR; // invalid priority
}
#ifdef DBKCD
rtx_dbug_outs("[CHECK_PARAMETERS] SUCCESS Valid Set Priority Command parameters \n\r");
#endif
return RTX_SUCCESS;
}
else if(in_cmd == 0x5a) {
// Z
// process A1
int i = 0;
while(in_param[i] == 0x20) {i++;}
if(in_param[i] != '\0') {
return RTX_ERROR; // This command is parameterless
}
return RTX_SUCCESS;
}
else if(in_cmd == 0x59) {
// Y
// process A2
int i = 0;
while(in_param[i] == 0x20) {i++;}
if(in_param[i] != '\0') {
return RTX_ERROR; // This command is parameterless
}
return RTX_SUCCESS;
}
else if(in_cmd == 0x58) {
// X
// process A3
int i = 0;
while(in_param[i] == 0x20) {i++;}
if(in_param[i] != '\0') {
return RTX_ERROR; // This command is parameterless
}
return RTX_SUCCESS;
}
else {
return RTX_ERROR; // Not a recognized command
}
}
int print_cmd_table() {
int i = 0;
char tmp_buf[2] = {0,0};
for(; i<cmd_table_cnt; i++) {
tmp_buf[0] = cmd_table[i].cmd;
rtx_dbug_outs("cmd: ");
rtx_dbug_outs(tmp_buf);
rtx_dbug_outs("; pid: ");
rtx_dbug_out_int10(cmd_table[i].pid);
rtx_dbug_outs("\n\r");
}
}
BOOL is_command_char(char in_cmd) {
return in_cmd == 0x25 /* '%' */ ? TRUE : FALSE;
}
/*
int verify_command(char* in_cmd) { // '%' <cmd_char>
PROCESS_ID tmp_pid = search_command(in_cmd);
if(tmp_pid == INVALID_PID) {
return RTX_ERROR;
}
else {
return RTX_SUCCESS;
}
}
*/
// assume command identifier is only a single char, and everything after it are parameters
PROCESS_ID search_command(char in_cmd) {
int i = 0;
for(; i<cmd_table_cnt; i++) {
if(cmd_table[i].cmd == in_cmd) {
return cmd_table[i].pid;
}
}
return RTX_ERROR;
}
int register_command(char in_cmd) {
#ifdef DBKCD
rtx_dbug_outs("[REGISTER_COMMAND] ");
rtx_dbug_out_int10(cmd_table_cnt);
rtx_dbug_outs(" commands registered\n\r");
#endif
char tmp_str[2] = {'\0', '\0'};
tmp_str[0] = in_cmd;
process_registration(in_cmd, pcb_get_pid(current_process));
if(search_command(in_cmd) != RTX_ERROR) {
#ifdef DBKCD
rtx_dbug_outs("[REGISTER_COMMAND] Command '");
rtx_dbug_outs(tmp_str);
rtx_dbug_outs("' already registered\n\r");
#endif
return RTX_SUCCESS; // command already registered
}
#ifdef DBKCD
rtx_dbug_outs("[REGISTER_COMMAND] Requesting envelope to send registration \n\r");
#endif
envl* tmp_envl = (envl*)request_memory_block();
#ifdef DBKCD
rtx_dbug_outs("[REGISTER_COMMAND] Sending message to register command '");
rtx_dbug_outs(tmp_str);
rtx_dbug_outs("'\n\r");
#endif
envl_set_message_type(tmp_envl, KCD_REGISTER);
envl_set_msgtext(tmp_envl, tmp_str);
return send_message(KCD_PID, (void*)tmp_envl);
}
int process_registration(char in_cmd, PROCESS_ID in_pid) {
if(!is_valid_pid(in_pid)) {
return RTX_ERROR;
}
// check if command already in table; otherwise add. If it is already in the table, re-register
int i = 0;
for(; i<cmd_table_cnt; i++) {
if(cmd_table[cmd_table_cnt].cmd == in_cmd) {
// it has already been registered
// so re-register
cmd_table[cmd_table_cnt].cmd = in_cmd;
cmd_table[cmd_table_cnt].pid = in_pid;
return RTX_SUCCESS;
}
}
if(i >= MAX_CMD_COUNT) {
return RTX_ERROR; // need to allocate more space for cmd_table
}
cmd_table[i].cmd = in_cmd;
cmd_table[i].pid = in_pid;
++cmd_table_cnt;
return RTX_SUCCESS;
}
void keyboard_command_decoder() {
#ifdef DBKCD
rtx_dbug_outs("============================================\n\r");
rtx_dbug_outs("[KEYBOARD_COMMAND_DECODER] Entering...\n\r");
#endif
const int buffsize = ENVL_MSGTEXT_SIZE;
char buffer[buffsize]; // contains user input // me: might need to do buffsize +1 here and have buffer[buffsize] = '\0' always (which no one should know about) // maybe want to do the same for envl.msgtext[] (although this might throw off other calculations)
int buffcnt = 0; // buffer count
while(1) {
#ifdef DBKCD
rtx_dbug_outs("[KCD] Calling receive_message()\n\r");
#endif
envl* tmp_envl = (envl*)receive_message(NULL);
#ifdef DBKCD
rtx_dbug_outs("[KCD] tmp_envl = ");
rtx_dbug_out_int16((UINT32)tmp_envl);
rtx_dbug_outs("\n\r");
#endif
// register commands
if(tmp_envl != NULL && envl_get_message_type(tmp_envl) == KCD_REGISTER && envl_get_sender_id(tmp_envl) != UART_I_PID) {
char* tmp_msgtext = envl_get_msgtext(tmp_envl);
// tmp_msgtext should be one character only
process_registration(*tmp_msgtext, envl_get_sender_id(tmp_envl));
#ifdef DBKCD
rtx_dbug_outs("[KCD] sender = ");
rtx_dbug_outs(pcb_get_name(peek_pcb(envl_get_sender_id(tmp_envl))));
rtx_dbug_outs("\n\r");
rtx_dbug_outs("[KCD] registration char = ");
rtx_dbug_outs(tmp_msgtext);
rtx_dbug_outs("\n\r");
/*
rtx_dbug_outs("[KCD] # cmd in table = ");
rtx_dbug_out_int10(cmd_table_cnt);
rtx_dbug_outs("\n\r");
*/
//rtx_dbug_outs("[KCD] Printing cmd_table");
//print_cmd_table();
//rtx_dbug_outs("\n\r");
#endif
// done reading message
release_memory_block((void*)tmp_envl);
}
// keyboard input
if(envl_get_sender_id(tmp_envl) == UART_I_PID) {
char* tmp_msgtext = envl_get_msgtext(tmp_envl);
char tmp_value = *tmp_msgtext; // is 1 char
#ifdef DBKCD
rtx_dbug_outs("[KCD] keyboard input = '");
rtx_dbug_outs(envl_get_msgtext(tmp_envl));
rtx_dbug_outs("'\n\r");
rtx_dbug_outs("[KCD] Now sending to CRT display...\n\r");
#endif
// set the MESSAGE_TYPE of the envl to CRT_DISPLAY
envl_set_message_type(tmp_envl, CRT_DISPLAY);
// send the envelope to the CRT to be displayed
send_message(CRT_DISPLAY_PID,tmp_envl);
// todo: move
/*
buffer[buffcnt] = tmp_value;
buffcnt++;
buffer[buffcnt] = '\0'
*/
// up here since a character should always go into the buffer (and since this reduces the number of places where buffering occurs (thereby reducing amount of places needing checking))
// todo: also, add a check to see if buffcnt >= ENVL_MSGTEXT_SIZE and null terminate immediately instead if so (assuming buffer[ENVL_MSGTEXT_SIZE+1])
if(tmp_value == 0x0a) { // LF
//buffer[buffcnt] = tmp_value;
//buffcnt++;
buffer[buffcnt] = '\0';
#ifdef DBKCD
rtx_dbug_outs("[KCD] buffered input = '");
rtx_dbug_outs(buffer);
rtx_dbug_outs("'\n\r");
#endif
// 1+ chars in buffer[]
// first two chars should be '%' <cmd_char>
char tmp_percent_char = buffer[0];
char tmp_cmd_char = buffer[1];
char* tmp_param = &buffer[2];
PROCESS_ID tmp_pid = search_command(tmp_cmd_char);
if(is_command_char(tmp_percent_char) == FALSE || // not a '%'
tmp_pid == RTX_ERROR) { // ie. not registered
clear_buffer(buffer, buffsize);
buffcnt = 0;
//#ifdef DBKCD
rtx_dbug_outs("[KCD] Not a command or not registered\n\r");
//#endif
}
else {
// tmp_percent_char == '%'
// tmp_cmd_char == <cmd_char>
int res = check_parameters(tmp_cmd_char, tmp_param);
if(res == RTX_ERROR) {
clear_buffer(buffer, buffsize);
buffcnt = 0;
//#ifdef DBKCD
rtx_dbug_outs("[KCD] Command char or parameters malformed\n\r");
//#endif
}
else {
envl* tmp_envl2 = (envl*)request_memory_block();
char* tmp_msgtext = envl_get_msgtext(tmp_envl2);
#ifdef DBSPC
rtx_dbug_outs("[KCD] buffered inpu2t = '");
rtx_dbug_outs(buffer);
rtx_dbug_outs("'\n\r");
#endif
copy_buffer(buffer, tmp_msgtext, buffsize);
#ifdef DEBUG
rtx_dbug_outs("[KCD] after copy = '");
rtx_dbug_outs(buffer);
rtx_dbug_outs("'\n\r");
#endif
clear_buffer(buffer, buffsize);
buffcnt = 0;
#ifdef DBSPC
rtx_dbug_outs("[KCD] Sending '");
rtx_dbug_outs(tmp_msgtext);
rtx_dbug_outs("' to ");
rtx_dbug_outs(pcb_get_name(peek_pcb(tmp_pid)));
rtx_dbug_outs("\n\r");
#endif
send_message(tmp_pid,tmp_envl2);
}
}
}
else { // if any other character is received then add to the buffer
if (buffcnt < (ENVL_MSGTEXT_SIZE-1)){
buffer[buffcnt] = tmp_value;
buffcnt++;
buffer[buffcnt] = '\0'; // assuming buffcnt < ENVL_MSGTEXT_SIZE (if buffer[ENVL_MSGTEXT_SIZE+1]) // this way, the buffer is always null terminated
#ifdef DBKCD
rtx_dbug_outs("[KCD] buffer =");
rtx_dbug_outs(buffer);
rtx_dbug_outs("\n\r");
#endif
}
#ifdef DBKCD
rtx_dbug_outs("[KCD] Character placed in buffer\n\r");
#endif
}
}
}
}