]>
Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* |
2 | * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. | |
3 | * | |
4 | * This software may be freely used, copied, modified, and distributed | |
5 | * provided that the above copyright notice is preserved in all copies of the | |
6 | * software. | |
7 | */ | |
8 | ||
9 | /* -*-C-*- | |
10 | * | |
11 | * $Revision$ | |
12 | * $Date$ | |
13 | * | |
14 | * | |
15 | * serdrv.c - Synchronous Serial Driver for Angel. | |
16 | * This is nice and simple just to get something going. | |
17 | */ | |
18 | ||
19 | #ifdef __hpux | |
20 | # define _POSIX_SOURCE 1 | |
21 | #endif | |
22 | ||
23 | #include <stdio.h> | |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | ||
27 | #include "crc.h" | |
28 | #include "devices.h" | |
29 | #include "buffers.h" | |
30 | #include "rxtx.h" | |
31 | #include "hostchan.h" | |
32 | #include "params.h" | |
33 | #include "logging.h" | |
34 | ||
0d06e24b JM |
35 | extern int baud_rate; /* From gdb/top.c */ |
36 | ||
c906108c SS |
37 | #ifdef COMPILING_ON_WINDOWS |
38 | # undef ERROR | |
39 | # undef IGNORE | |
40 | # include <windows.h> | |
41 | # include "angeldll.h" | |
42 | # include "comb_api.h" | |
43 | #else | |
44 | # ifdef __hpux | |
45 | # define _TERMIOS_INCLUDED | |
46 | # include <sys/termio.h> | |
47 | # undef _TERMIOS_INCLUDED | |
48 | # else | |
49 | # include <termios.h> | |
50 | # endif | |
51 | # include "unixcomm.h" | |
52 | #endif | |
53 | ||
54 | #ifndef UNUSED | |
55 | # define UNUSED(x) (x = x) /* Silence compiler warnings */ | |
56 | #endif | |
57 | ||
58 | #define MAXREADSIZE 512 | |
59 | #define MAXWRITESIZE 512 | |
60 | ||
61 | #define SERIAL_FC_SET ((1<<serial_XON)|(1<<serial_XOFF)) | |
62 | #define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC)) | |
63 | #define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET) | |
64 | ||
65 | static const struct re_config config = { | |
66 | serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */ | |
67 | SERIAL_FC_SET, /* set of flow-control characters */ | |
68 | SERIAL_ESC_SET, /* set of characters to be escaped */ | |
69 | NULL /* serial_flow_control */, NULL , /* what to do with FC chars */ | |
70 | angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */ | |
71 | }; | |
72 | ||
73 | static struct re_state rxstate; | |
74 | ||
75 | typedef struct writestate { | |
76 | unsigned int wbindex; | |
77 | /* static te_status testatus;*/ | |
78 | unsigned char writebuf[MAXWRITESIZE]; | |
79 | struct te_state txstate; | |
80 | } writestate; | |
81 | ||
82 | static struct writestate wstate; | |
83 | ||
84 | /* | |
85 | * The set of parameter options supported by the device | |
86 | */ | |
87 | static unsigned int baud_options[] = { | |
c5394b80 | 88 | #if defined(B115200) || defined(__hpux) |
0d06e24b JM |
89 | 115200, |
90 | #endif | |
c5394b80 | 91 | #if defined(B57600) || defined(__hpux) |
0d06e24b | 92 | 57600, |
c906108c SS |
93 | #endif |
94 | 38400, 19200, 9600 | |
95 | }; | |
96 | ||
97 | static ParameterList param_list[] = { | |
98 | { AP_BAUD_RATE, | |
99 | sizeof(baud_options)/sizeof(unsigned int), | |
100 | baud_options } | |
101 | }; | |
102 | ||
103 | static const ParameterOptions serial_options = { | |
104 | sizeof(param_list)/sizeof(ParameterList), param_list }; | |
105 | ||
106 | /* | |
107 | * The default parameter config for the device | |
108 | */ | |
109 | static Parameter param_default[] = { | |
110 | { AP_BAUD_RATE, 9600 } | |
111 | }; | |
112 | ||
113 | static ParameterConfig serial_defaults = { | |
114 | sizeof(param_default)/sizeof(Parameter), param_default }; | |
115 | ||
116 | /* | |
117 | * The user-modified options for the device | |
118 | */ | |
119 | static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)]; | |
120 | ||
121 | static ParameterList param_user_list[] = { | |
122 | { AP_BAUD_RATE, | |
123 | sizeof(user_baud_options)/sizeof(unsigned), | |
124 | user_baud_options } | |
125 | }; | |
126 | ||
127 | static ParameterOptions user_options = { | |
128 | sizeof(param_user_list)/sizeof(ParameterList), param_user_list }; | |
129 | ||
130 | static bool user_options_set; | |
131 | ||
132 | /* forward declarations */ | |
133 | static int serial_reset( void ); | |
134 | static int serial_set_params( const ParameterConfig *config ); | |
135 | static int SerialMatch(const char *name, const char *arg); | |
136 | ||
137 | static void process_baud_rate( unsigned int target_baud_rate ) | |
138 | { | |
139 | const ParameterList *full_list; | |
140 | ParameterList *user_list; | |
141 | ||
142 | /* create subset of full options */ | |
143 | full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE ); | |
144 | user_list = Angel_FindParamList( &user_options, AP_BAUD_RATE ); | |
145 | ||
146 | if ( full_list != NULL && user_list != NULL ) | |
147 | { | |
148 | unsigned int i, j; | |
149 | unsigned int def_baud = 0; | |
150 | ||
151 | /* find lower or equal to */ | |
152 | for ( i = 0; i < full_list->num_options; ++i ) | |
153 | if ( target_baud_rate >= full_list->option[i] ) | |
154 | { | |
155 | /* copy remaining */ | |
156 | for ( j = 0; j < (full_list->num_options - i); ++j ) | |
157 | user_list->option[j] = full_list->option[i+j]; | |
158 | user_list->num_options = j; | |
159 | ||
160 | /* check this is not the default */ | |
161 | Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud ); | |
162 | if ( (j == 1) && (user_list->option[0] == def_baud) ) | |
163 | { | |
164 | #ifdef DEBUG | |
165 | printf( "user selected default\n" ); | |
166 | #endif | |
167 | } | |
168 | else | |
169 | { | |
170 | user_options_set = TRUE; | |
171 | #ifdef DEBUG | |
172 | printf( "user options are: " ); | |
173 | for ( j = 0; j < user_list->num_options; ++j ) | |
174 | printf( "%u ", user_list->option[j] ); | |
175 | printf( "\n" ); | |
176 | #endif | |
177 | } | |
178 | ||
179 | break; /* out of i loop */ | |
180 | } | |
181 | ||
182 | #ifdef DEBUG | |
183 | if ( i >= full_list->num_options ) | |
184 | printf( "couldn't match baud rate %u\n", target_baud_rate ); | |
185 | #endif | |
186 | } | |
187 | #ifdef DEBUG | |
188 | else | |
189 | printf( "failed to find lists\n" ); | |
190 | #endif | |
191 | } | |
192 | ||
193 | static int SerialOpen(const char *name, const char *arg) | |
194 | { | |
195 | const char *port_name = name; | |
196 | ||
197 | #ifdef DEBUG | |
198 | printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>"); | |
199 | #endif | |
200 | ||
201 | #ifdef COMPILING_ON_WINDOWS | |
202 | if (IsOpenSerial()) return -1; | |
203 | #else | |
204 | if (Unix_IsSerialInUse()) return -1; | |
205 | #endif | |
206 | ||
207 | #ifdef COMPILING_ON_WINDOWS | |
208 | if (SerialMatch(name, arg) != adp_ok) | |
209 | return adp_failed; | |
210 | #else | |
211 | port_name = Unix_MatchValidSerialDevice(port_name); | |
212 | # ifdef DEBUG | |
213 | printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name); | |
214 | # endif | |
215 | if (port_name == 0) return adp_failed; | |
216 | #endif | |
217 | ||
218 | user_options_set = FALSE; | |
219 | ||
220 | /* interpret and store the arguments */ | |
221 | if ( arg != NULL ) | |
222 | { | |
223 | unsigned int target_baud_rate; | |
224 | target_baud_rate = (unsigned int)strtoul(arg, NULL, 10); | |
225 | if (target_baud_rate > 0) | |
226 | { | |
227 | #ifdef DEBUG | |
228 | printf( "user selected baud rate %u\n", target_baud_rate ); | |
229 | #endif | |
230 | process_baud_rate( target_baud_rate ); | |
231 | } | |
232 | #ifdef DEBUG | |
233 | else | |
234 | printf( "could not understand baud rate %s\n", arg ); | |
235 | #endif | |
236 | } | |
0d06e24b JM |
237 | else if (baud_rate > 0) |
238 | { | |
239 | /* If the user specified a baud rate on the command line "-b" or via | |
240 | the "set remotebaud" command then try to use that one */ | |
241 | process_baud_rate( baud_rate ); | |
242 | } | |
c906108c SS |
243 | |
244 | #ifdef COMPILING_ON_WINDOWS | |
245 | { | |
246 | int port = IsValidDevice(name); | |
247 | if (OpenSerial(port, FALSE) != COM_OK) | |
248 | return -1; | |
249 | } | |
250 | #else | |
251 | if (Unix_OpenSerial(port_name) < 0) | |
252 | return -1; | |
253 | #endif | |
254 | ||
255 | serial_reset(); | |
256 | ||
257 | #if defined(__unix) || defined(__CYGWIN32__) | |
258 | Unix_ioctlNonBlocking(); | |
259 | #endif | |
260 | ||
261 | Angel_RxEngineInit(&config, &rxstate); | |
262 | /* | |
263 | * DANGER!: passing in NULL as the packet is ok for now as it is just | |
264 | * IGNOREd but this may well change | |
265 | */ | |
266 | Angel_TxEngineInit(&config, NULL, &wstate.txstate); | |
267 | return 0; | |
268 | } | |
269 | ||
270 | static int SerialMatch(const char *name, const char *arg) | |
271 | { | |
272 | UNUSED(arg); | |
273 | #ifdef COMPILING_ON_WINDOWS | |
274 | if (IsValidDevice(name) == COM_DEVICENOTVALID) | |
275 | return -1; | |
276 | else | |
277 | return 0; | |
278 | #else | |
279 | return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0; | |
280 | #endif | |
281 | } | |
282 | ||
283 | static void SerialClose(void) | |
284 | { | |
285 | #ifdef DO_TRACE | |
286 | printf("SerialClose()\n"); | |
287 | #endif | |
288 | ||
289 | #ifdef COMPILING_ON_WINDOWS | |
290 | CloseSerial(); | |
291 | #else | |
292 | Unix_CloseSerial(); | |
293 | #endif | |
294 | } | |
295 | ||
296 | static int SerialRead(DriverCall *dc, bool block) { | |
297 | static unsigned char readbuf[MAXREADSIZE]; | |
298 | static int rbindex=0; | |
299 | ||
300 | int nread; | |
301 | int read_errno; | |
302 | int c=0; | |
303 | re_status restatus; | |
304 | int ret_code = -1; /* assume bad packet or error */ | |
305 | ||
306 | /* must not overflow buffer and must start after the existing data */ | |
307 | #ifdef COMPILING_ON_WINDOWS | |
308 | { | |
309 | BOOL dummy = FALSE; | |
310 | nread = BytesInRXBufferSerial(); | |
311 | ||
312 | if (nread > MAXREADSIZE - rbindex) | |
313 | nread = MAXREADSIZE - rbindex; | |
314 | ||
315 | if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL) | |
316 | { | |
317 | MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP); | |
318 | return -1; /* SJ - This really needs to return a value, which is picked up in */ | |
319 | /* DevSW_Read as meaning stop debugger but don't kill. */ | |
320 | } | |
321 | else if (pfnProgressCallback != NULL && read_errno == COM_OK) | |
322 | { | |
323 | progressInfo.nRead += nread; | |
324 | (*pfnProgressCallback)(&progressInfo); | |
325 | } | |
326 | } | |
327 | #else | |
328 | nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block); | |
329 | read_errno = errno; | |
330 | #endif | |
331 | ||
332 | if ((nread > 0) || (rbindex > 0)) { | |
333 | ||
334 | #ifdef DO_TRACE | |
335 | printf("[%d@%d] ", nread, rbindex); | |
336 | #endif | |
337 | ||
338 | if (nread>0) | |
339 | rbindex = rbindex+nread; | |
340 | ||
341 | do { | |
342 | restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate); | |
343 | #ifdef DO_TRACE | |
344 | printf("<%02X ",readbuf[c]); | |
345 | if (!(++c % 16)) | |
346 | printf("\n"); | |
347 | #else | |
348 | c++; | |
349 | #endif | |
350 | } while (c<rbindex && | |
351 | ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT))); | |
352 | ||
353 | #ifdef DO_TRACE | |
354 | if (c % 16) | |
355 | printf("\n"); | |
356 | #endif | |
357 | ||
358 | switch(restatus) { | |
359 | ||
360 | case RS_GOOD_PKT: | |
361 | ret_code = 1; | |
362 | /* fall through to: */ | |
363 | ||
364 | case RS_BAD_PKT: | |
365 | /* | |
366 | * We now need to shuffle any left over data down to the | |
367 | * beginning of our private buffer ready to be used | |
368 | *for the next packet | |
369 | */ | |
370 | #ifdef DO_TRACE | |
371 | printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c); | |
372 | #endif | |
373 | if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c), | |
374 | rbindex-c); | |
375 | rbindex -= c; | |
376 | break; | |
377 | ||
378 | case RS_IN_PKT: | |
379 | case RS_WAIT_PKT: | |
380 | rbindex = 0; /* will have processed all we had */ | |
381 | ret_code = 0; | |
382 | break; | |
383 | ||
384 | default: | |
385 | #ifdef DEBUG | |
386 | printf("Bad re_status in serialRead()\n"); | |
387 | #endif | |
388 | break; | |
389 | } | |
390 | } else if (nread == 0) | |
391 | ret_code = 0; /* nothing to read */ | |
392 | else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */ | |
393 | ret_code = 0; | |
394 | ||
395 | #ifdef DEBUG | |
396 | if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO)) | |
397 | perror("read() error in serialRead()"); | |
398 | #endif | |
399 | ||
400 | return ret_code; | |
401 | } | |
402 | ||
403 | ||
404 | static int SerialWrite(DriverCall *dc) { | |
405 | int nwritten = 0; | |
406 | te_status testatus = TS_IN_PKT; | |
407 | ||
408 | if (dc->dc_context == NULL) { | |
409 | Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate)); | |
410 | wstate.wbindex = 0; | |
411 | dc->dc_context = &wstate; | |
412 | } | |
413 | ||
414 | while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE)) | |
415 | { | |
416 | /* send the raw data through the tx engine to escape and encapsulate */ | |
417 | testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate), | |
418 | &(wstate.writebuf)[wstate.wbindex]); | |
419 | if (testatus != TS_IDLE) wstate.wbindex++; | |
420 | } | |
421 | ||
422 | if (testatus == TS_IDLE) { | |
423 | #ifdef DEBUG | |
424 | printf("SerialWrite: testatus is TS_IDLE during preprocessing\n"); | |
425 | #endif | |
426 | } | |
427 | ||
428 | #ifdef DO_TRACE | |
429 | { | |
430 | int i = 0; | |
431 | ||
432 | while (i<wstate.wbindex) | |
433 | { | |
434 | printf(">%02X ",wstate.writebuf[i]); | |
435 | ||
436 | if (!(++i % 16)) | |
437 | printf("\n"); | |
438 | } | |
439 | if (i % 16) | |
440 | printf("\n"); | |
441 | } | |
442 | #endif | |
443 | ||
444 | #ifdef COMPILING_ON_WINDOWS | |
445 | if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK) | |
446 | { | |
447 | nwritten = wstate.wbindex; | |
448 | if (pfnProgressCallback != NULL) | |
449 | { | |
450 | progressInfo.nWritten += nwritten; | |
451 | (*pfnProgressCallback)(&progressInfo); | |
452 | } | |
453 | } | |
454 | else | |
455 | { | |
456 | MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP); | |
457 | return -1; /* SJ - This really needs to return a value, which is picked up in */ | |
458 | /* DevSW_Read as meaning stop debugger but don't kill. */ | |
459 | } | |
460 | #else | |
461 | nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex); | |
462 | ||
463 | if (nwritten < 0) { | |
464 | nwritten=0; | |
465 | } | |
466 | #endif | |
467 | ||
468 | #ifdef DEBUG | |
469 | if (nwritten > 0) | |
470 | printf("Wrote %#04x bytes\n", nwritten); | |
471 | #endif | |
472 | ||
473 | if ((unsigned) nwritten == wstate.wbindex && | |
474 | (testatus == TS_DONE_PKT || testatus == TS_IDLE)) { | |
475 | ||
476 | /* finished sending the packet */ | |
477 | ||
478 | #ifdef DEBUG | |
479 | printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex); | |
480 | #endif | |
481 | testatus = TS_IN_PKT; | |
482 | wstate.wbindex = 0; | |
483 | return 1; | |
484 | } | |
485 | else { | |
486 | #ifdef DEBUG | |
487 | printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n", | |
488 | wstate.wbindex, nwritten); | |
489 | #endif | |
490 | ||
491 | /* | |
492 | * still some data left to send shuffle whats left down and reset | |
493 | * the ptr | |
494 | */ | |
495 | memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten), | |
496 | wstate.wbindex-nwritten); | |
497 | wstate.wbindex -= nwritten; | |
498 | return 0; | |
499 | } | |
500 | return -1; | |
501 | } | |
502 | ||
503 | ||
504 | static int serial_reset( void ) | |
505 | { | |
506 | #ifdef DEBUG | |
507 | printf( "serial_reset\n" ); | |
508 | #endif | |
509 | ||
510 | #ifdef COMPILING_ON_WINDOWS | |
511 | FlushSerial(); | |
512 | #else | |
513 | Unix_ResetSerial(); | |
514 | #endif | |
515 | ||
516 | return serial_set_params( &serial_defaults ); | |
517 | } | |
518 | ||
519 | ||
520 | static int find_baud_rate( unsigned int *speed ) | |
521 | { | |
522 | static struct { | |
523 | unsigned int baud; | |
524 | int termiosValue; | |
525 | } possibleBaudRates[] = { | |
526 | #if defined(__hpux) | |
527 | {115200,_B115200}, {57600,_B57600}, | |
0d06e24b JM |
528 | #else |
529 | #ifdef B115200 | |
530 | {115200,B115200}, | |
531 | #endif | |
532 | #ifdef B57600 | |
533 | {57600,B57600}, | |
534 | #endif | |
c906108c SS |
535 | #endif |
536 | #ifdef COMPILING_ON_WINDOWS | |
537 | {38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0} | |
538 | #else | |
539 | {38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0} | |
540 | #endif | |
541 | }; | |
542 | unsigned int i; | |
543 | ||
544 | /* look for lower or matching -- will always terminate at 0 end marker */ | |
545 | for ( i = 0; possibleBaudRates[i].baud > *speed; ++i ) | |
546 | /* do nothing */ ; | |
547 | ||
548 | if ( possibleBaudRates[i].baud > 0 ) | |
549 | *speed = possibleBaudRates[i].baud; | |
550 | ||
551 | return possibleBaudRates[i].termiosValue; | |
552 | } | |
553 | ||
554 | ||
555 | static int serial_set_params( const ParameterConfig *config ) | |
556 | { | |
557 | unsigned int speed; | |
558 | int termios_value; | |
559 | ||
560 | #ifdef DEBUG | |
561 | printf( "serial_set_params\n" ); | |
562 | #endif | |
563 | ||
564 | if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) ) | |
565 | { | |
566 | #ifdef DEBUG | |
567 | printf( "speed not found in config\n" ); | |
568 | #endif | |
569 | return DE_OKAY; | |
570 | } | |
571 | ||
572 | termios_value = find_baud_rate( &speed ); | |
573 | if ( termios_value == 0 ) | |
574 | { | |
575 | #ifdef DEBUG | |
576 | printf( "speed not valid: %u\n", speed ); | |
577 | #endif | |
578 | return DE_OKAY; | |
579 | } | |
580 | ||
581 | #ifdef DEBUG | |
582 | printf( "setting speed to %u\n", speed ); | |
583 | #endif | |
584 | ||
585 | #ifdef COMPILING_ON_WINDOWS | |
586 | SetBaudRate((WORD)termios_value); | |
587 | #else | |
588 | Unix_SetSerialBaudRate(termios_value); | |
589 | #endif | |
590 | ||
591 | return DE_OKAY; | |
592 | } | |
593 | ||
594 | ||
595 | static int serial_get_user_params( ParameterOptions **p_options ) | |
596 | { | |
597 | #ifdef DEBUG | |
598 | printf( "serial_get_user_params\n" ); | |
599 | #endif | |
600 | ||
601 | if ( user_options_set ) | |
602 | { | |
603 | *p_options = &user_options; | |
604 | } | |
605 | else | |
606 | { | |
607 | *p_options = NULL; | |
608 | } | |
609 | ||
610 | return DE_OKAY; | |
611 | } | |
612 | ||
613 | ||
614 | static int serial_get_default_params( ParameterConfig **p_config ) | |
615 | { | |
616 | #ifdef DEBUG | |
617 | printf( "serial_get_default_params\n" ); | |
618 | #endif | |
619 | ||
620 | *p_config = (ParameterConfig *) &serial_defaults; | |
621 | return DE_OKAY; | |
622 | } | |
623 | ||
624 | ||
625 | static int SerialIoctl(const int opcode, void *args) { | |
626 | ||
627 | int ret_code; | |
628 | ||
629 | #ifdef DEBUG | |
630 | printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>"); | |
631 | #endif | |
632 | ||
633 | switch (opcode) | |
634 | { | |
635 | case DC_RESET: | |
636 | ret_code = serial_reset(); | |
637 | break; | |
638 | ||
639 | case DC_SET_PARAMS: | |
640 | ret_code = serial_set_params((const ParameterConfig *)args); | |
641 | break; | |
642 | ||
643 | case DC_GET_USER_PARAMS: | |
644 | ret_code = serial_get_user_params((ParameterOptions **)args); | |
645 | break; | |
646 | ||
647 | case DC_GET_DEFAULT_PARAMS: | |
648 | ret_code = serial_get_default_params((ParameterConfig **)args); | |
649 | break; | |
650 | ||
651 | default: | |
652 | ret_code = DE_BAD_OP; | |
653 | break; | |
654 | } | |
655 | ||
656 | return ret_code; | |
657 | } | |
658 | ||
659 | DeviceDescr angel_SerialDevice = { | |
660 | "SERIAL", | |
661 | SerialOpen, | |
662 | SerialMatch, | |
663 | SerialClose, | |
664 | SerialRead, | |
665 | SerialWrite, | |
666 | SerialIoctl | |
667 | }; |